@hasna/skills 0.10.50 → 0.10.52
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 +86 -5
- package/bin/index.js +1827 -1374
- package/bin/maintenance.js +199 -2
- package/bin/mcp.js +730 -482
- package/bin/migrate.js +1 -1
- package/bin/server.js +11 -4
- package/bin/worker.js +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1052 -704
- package/dist/lib/agent-discovery.d.ts +38 -2
- package/dist/lib/agent-integration.d.ts +4 -1
- package/dist/lib/claude-marketplace-entry-witness.d.ts +26 -0
- package/dist/lib/claude-settings-witness.d.ts +25 -1
- package/dist/lib/codex-hook-trust-files.d.ts +17 -0
- package/dist/lib/codex-native-compatibility.d.ts +4 -1
- package/dist/lib/selection-cache.d.ts +2 -2
- package/dist/lib/session-reconciliation.d.ts +9 -0
- package/dist/sdk/index.js +1001 -658
- package/dist/server/maintenance-entry.d.ts +14 -0
- package/dist/server/schema-census.d.ts +77 -0
- package/docs/plugin-admission.md +190 -3
- package/package.json +1 -1
package/dist/sdk/index.js
CHANGED
|
@@ -5267,8 +5267,8 @@ var require_cst_visit = __commonJS((exports) => {
|
|
|
5267
5267
|
visit.REMOVE = REMOVE;
|
|
5268
5268
|
visit.itemAtPath = (cst, path) => {
|
|
5269
5269
|
let item = cst;
|
|
5270
|
-
for (const [
|
|
5271
|
-
const tok = item?.[
|
|
5270
|
+
for (const [field2, index] of path) {
|
|
5271
|
+
const tok = item?.[field2];
|
|
5272
5272
|
if (tok && "items" in tok) {
|
|
5273
5273
|
item = tok.items[index];
|
|
5274
5274
|
} else
|
|
@@ -5278,8 +5278,8 @@ var require_cst_visit = __commonJS((exports) => {
|
|
|
5278
5278
|
};
|
|
5279
5279
|
visit.parentCollection = (cst, path) => {
|
|
5280
5280
|
const parent = visit.itemAtPath(cst, path.slice(0, -1));
|
|
5281
|
-
const
|
|
5282
|
-
const coll = parent?.[
|
|
5281
|
+
const field2 = path[path.length - 1][0];
|
|
5282
|
+
const coll = parent?.[field2];
|
|
5283
5283
|
if (coll && "items" in coll)
|
|
5284
5284
|
return coll;
|
|
5285
5285
|
throw new Error("Parent collection not found");
|
|
@@ -5288,11 +5288,11 @@ var require_cst_visit = __commonJS((exports) => {
|
|
|
5288
5288
|
let ctrl = visitor(item, path);
|
|
5289
5289
|
if (typeof ctrl === "symbol")
|
|
5290
5290
|
return ctrl;
|
|
5291
|
-
for (const
|
|
5292
|
-
const token = item[
|
|
5291
|
+
for (const field2 of ["key", "value"]) {
|
|
5292
|
+
const token = item[field2];
|
|
5293
5293
|
if (token && "items" in token) {
|
|
5294
5294
|
for (let i = 0;i < token.items.length; ++i) {
|
|
5295
|
-
const ci = _visit(Object.freeze(path.concat([[
|
|
5295
|
+
const ci = _visit(Object.freeze(path.concat([[field2, i]])), token.items[i], visitor);
|
|
5296
5296
|
if (typeof ci === "number")
|
|
5297
5297
|
i = ci - 1;
|
|
5298
5298
|
else if (ci === BREAK)
|
|
@@ -5302,7 +5302,7 @@ var require_cst_visit = __commonJS((exports) => {
|
|
|
5302
5302
|
i -= 1;
|
|
5303
5303
|
}
|
|
5304
5304
|
}
|
|
5305
|
-
if (typeof ctrl === "function" &&
|
|
5305
|
+
if (typeof ctrl === "function" && field2 === "key")
|
|
5306
5306
|
ctrl = ctrl(item, path);
|
|
5307
5307
|
}
|
|
5308
5308
|
}
|
|
@@ -5728,9 +5728,9 @@ var require_lexer = __commonJS((exports) => {
|
|
|
5728
5728
|
}
|
|
5729
5729
|
}
|
|
5730
5730
|
*parseQuotedScalar() {
|
|
5731
|
-
const
|
|
5732
|
-
let end = this.buffer.indexOf(
|
|
5733
|
-
if (
|
|
5731
|
+
const quote2 = this.charAt(0);
|
|
5732
|
+
let end = this.buffer.indexOf(quote2, this.pos + 1);
|
|
5733
|
+
if (quote2 === "'") {
|
|
5734
5734
|
while (end !== -1 && this.buffer[end + 1] === "'")
|
|
5735
5735
|
end = this.buffer.indexOf("'", end + 2);
|
|
5736
5736
|
} else {
|
|
@@ -8209,7 +8209,7 @@ var require_client = __commonJS((exports) => {
|
|
|
8209
8209
|
};
|
|
8210
8210
|
};
|
|
8211
8211
|
var sleep = (seconds) => {
|
|
8212
|
-
return new Promise((
|
|
8212
|
+
return new Promise((resolve24) => setTimeout(resolve24, seconds * 1000));
|
|
8213
8213
|
};
|
|
8214
8214
|
var waiterServiceDefaults = {
|
|
8215
8215
|
minDelay: 2,
|
|
@@ -8264,14 +8264,14 @@ var require_client = __commonJS((exports) => {
|
|
|
8264
8264
|
}
|
|
8265
8265
|
await sleep(delayMs / 1000);
|
|
8266
8266
|
}
|
|
8267
|
-
const { state, reason } = await acceptorChecks(client2, input);
|
|
8268
|
-
if (
|
|
8269
|
-
const message = createMessageFromResponse(
|
|
8267
|
+
const { state, reason: reason2 } = await acceptorChecks(client2, input);
|
|
8268
|
+
if (reason2) {
|
|
8269
|
+
const message = createMessageFromResponse(reason2);
|
|
8270
8270
|
observedResponses[message] |= 0;
|
|
8271
8271
|
observedResponses[message] += 1;
|
|
8272
8272
|
}
|
|
8273
8273
|
if (state !== WaiterState.RETRY) {
|
|
8274
|
-
return { state, reason, final:
|
|
8274
|
+
return { state, reason: reason2, final: reason2, observedResponses };
|
|
8275
8275
|
}
|
|
8276
8276
|
currentAttempt += 1;
|
|
8277
8277
|
if (!didWarn403 && Date.now() >= warn403Time) {
|
|
@@ -8295,18 +8295,18 @@ var require_client = __commonJS((exports) => {
|
|
|
8295
8295
|
warningLogger.warn(`@smithy/util-waiter WARN - 403 status code encountered during waiter polling.`);
|
|
8296
8296
|
}
|
|
8297
8297
|
};
|
|
8298
|
-
var createMessageFromResponse = (
|
|
8299
|
-
const status =
|
|
8300
|
-
if (
|
|
8301
|
-
return `${status ? status + ": " : ""}Deserialization error for body: ${
|
|
8298
|
+
var createMessageFromResponse = (reason2) => {
|
|
8299
|
+
const status = reason2?.$response?.statusCode ?? reason2?.$metadata?.httpStatusCode;
|
|
8300
|
+
if (reason2?.$responseBodyText) {
|
|
8301
|
+
return `${status ? status + ": " : ""}Deserialization error for body: ${reason2.$responseBodyText}`;
|
|
8302
8302
|
}
|
|
8303
8303
|
if (status) {
|
|
8304
|
-
if (
|
|
8305
|
-
return `${status ?? "Unknown"}: ${
|
|
8304
|
+
if (reason2?.$response || reason2?.message) {
|
|
8305
|
+
return `${status ?? "Unknown"}: ${reason2?.message}`;
|
|
8306
8306
|
}
|
|
8307
8307
|
return `${status}: OK`;
|
|
8308
8308
|
}
|
|
8309
|
-
return String(
|
|
8309
|
+
return String(reason2?.message ?? JSON.stringify(reason2, getCircularReplacer()) ?? "Unknown");
|
|
8310
8310
|
};
|
|
8311
8311
|
var exponentialBackoffWithJitter = (minDelayMs, maxDelayMs, attempt, waitUntil) => {
|
|
8312
8312
|
const attemptCountCeiling = Math.log(maxDelayMs / minDelayMs) / Math.log(2) + 1;
|
|
@@ -8338,8 +8338,8 @@ var require_client = __commonJS((exports) => {
|
|
|
8338
8338
|
};
|
|
8339
8339
|
var abortTimeout = (abortSignal) => {
|
|
8340
8340
|
let onAbort;
|
|
8341
|
-
const promise = new Promise((
|
|
8342
|
-
onAbort = () =>
|
|
8341
|
+
const promise = new Promise((resolve24) => {
|
|
8342
|
+
onAbort = () => resolve24({ state: WaiterState.ABORTED });
|
|
8343
8343
|
if (typeof abortSignal.addEventListener === "function") {
|
|
8344
8344
|
abortSignal.addEventListener("abort", onAbort);
|
|
8345
8345
|
} else {
|
|
@@ -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: sep11, join: join4 } = __require("path");
|
|
9007
|
-
var { createHash:
|
|
9007
|
+
var { createHash: createHash28 } = __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 = createHash28("sha1");
|
|
9163
9163
|
const cacheName = hasher.update(id2).digest("hex");
|
|
9164
9164
|
return join4(getHomeDir(), ".aws", "sso", "cache", `${cacheName}.json`);
|
|
9165
9165
|
};
|
|
@@ -9477,7 +9477,7 @@ var require_config = __commonJS((exports) => {
|
|
|
9477
9477
|
};
|
|
9478
9478
|
var imdsRequest = async (options) => {
|
|
9479
9479
|
const { request: request2 } = __require("http");
|
|
9480
|
-
return new Promise((
|
|
9480
|
+
return new Promise((resolve24, reject) => {
|
|
9481
9481
|
const req = request2({
|
|
9482
9482
|
hostname: options.hostname,
|
|
9483
9483
|
port: options.port,
|
|
@@ -9505,7 +9505,7 @@ var require_config = __commonJS((exports) => {
|
|
|
9505
9505
|
const chunks = [];
|
|
9506
9506
|
res.on("data", (chunk) => chunks.push(chunk));
|
|
9507
9507
|
res.on("end", () => {
|
|
9508
|
-
|
|
9508
|
+
resolve24(Buffer.concat(chunks));
|
|
9509
9509
|
req.destroy();
|
|
9510
9510
|
});
|
|
9511
9511
|
});
|
|
@@ -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: createHash28, getRandomValues } = __require("crypto");
|
|
10515
10515
|
var { hasOwn: hasOwn2, HttpResponse } = require_transport();
|
|
10516
10516
|
exports.hasOwn = hasOwn2;
|
|
10517
10517
|
var { ReadStream, lstatSync: lstatSync27, 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)) : createHash28(this.algorithmIdentifier);
|
|
11420
11420
|
}
|
|
11421
11421
|
}
|
|
11422
11422
|
function castSourceData(toCast, encoding) {
|
|
@@ -11861,7 +11861,7 @@ ${value}\r
|
|
|
11861
11861
|
if (isReadableStream(stream)) {
|
|
11862
11862
|
return headStream$1(stream, bytes);
|
|
11863
11863
|
}
|
|
11864
|
-
return new Promise((
|
|
11864
|
+
return new Promise((resolve24, reject) => {
|
|
11865
11865
|
const collector = new Collector$1;
|
|
11866
11866
|
collector.limit = bytes;
|
|
11867
11867
|
stream.pipe(collector);
|
|
@@ -11872,7 +11872,7 @@ ${value}\r
|
|
|
11872
11872
|
collector.on("error", reject);
|
|
11873
11873
|
collector.on("finish", function() {
|
|
11874
11874
|
const bytes2 = concatBytes(this.buffers);
|
|
11875
|
-
|
|
11875
|
+
resolve24(bytes2);
|
|
11876
11876
|
});
|
|
11877
11877
|
});
|
|
11878
11878
|
};
|
|
@@ -11986,7 +11986,7 @@ ${value}\r
|
|
|
11986
11986
|
if (isReadableStream(stream)) {
|
|
11987
11987
|
return collectReadableStream(stream);
|
|
11988
11988
|
}
|
|
11989
|
-
return new Promise((
|
|
11989
|
+
return new Promise((resolve24, reject) => {
|
|
11990
11990
|
const collector = new Collector;
|
|
11991
11991
|
const nodeStream = stream;
|
|
11992
11992
|
nodeStream.pipe(collector);
|
|
@@ -11997,7 +11997,7 @@ ${value}\r
|
|
|
11997
11997
|
collector.on("error", reject);
|
|
11998
11998
|
collector.on("finish", function() {
|
|
11999
11999
|
const bytes = concatBytes(this.bufferedBytes);
|
|
12000
|
-
|
|
12000
|
+
resolve24(bytes);
|
|
12001
12001
|
});
|
|
12002
12002
|
});
|
|
12003
12003
|
};
|
|
@@ -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: createHash28, 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;
|
|
@@ -12189,7 +12189,7 @@ var require_checksum = __commonJS((exports) => {
|
|
|
12189
12189
|
callback();
|
|
12190
12190
|
}
|
|
12191
12191
|
}
|
|
12192
|
-
var fileStreamHasher = (hashCtor, fileStream) => new Promise((
|
|
12192
|
+
var fileStreamHasher = (hashCtor, fileStream) => new Promise((resolve24, reject) => {
|
|
12193
12193
|
if (!isReadStream(fileStream)) {
|
|
12194
12194
|
reject(new Error("Unable to calculate hash for non-file streams."));
|
|
12195
12195
|
return;
|
|
@@ -12207,7 +12207,7 @@ var require_checksum = __commonJS((exports) => {
|
|
|
12207
12207
|
});
|
|
12208
12208
|
hashCalculator.on("error", reject);
|
|
12209
12209
|
hashCalculator.on("finish", function() {
|
|
12210
|
-
hash2.digest().then(
|
|
12210
|
+
hash2.digest().then(resolve24).catch(reject);
|
|
12211
12211
|
});
|
|
12212
12212
|
});
|
|
12213
12213
|
var isReadStream = (stream) => typeof stream.path === "string";
|
|
@@ -12218,14 +12218,14 @@ var require_checksum = __commonJS((exports) => {
|
|
|
12218
12218
|
const hash2 = new hashCtor;
|
|
12219
12219
|
const hashCalculator = new HashCalculator(hash2);
|
|
12220
12220
|
readableStream.pipe(hashCalculator);
|
|
12221
|
-
return new Promise((
|
|
12221
|
+
return new Promise((resolve24, reject) => {
|
|
12222
12222
|
readableStream.on("error", (err) => {
|
|
12223
12223
|
hashCalculator.end();
|
|
12224
12224
|
reject(err);
|
|
12225
12225
|
});
|
|
12226
12226
|
hashCalculator.on("error", reject);
|
|
12227
12227
|
hashCalculator.on("finish", () => {
|
|
12228
|
-
hash2.digest().then(
|
|
12228
|
+
hash2.digest().then(resolve24).catch(reject);
|
|
12229
12229
|
});
|
|
12230
12230
|
});
|
|
12231
12231
|
};
|
|
@@ -12320,7 +12320,7 @@ var require_checksum = __commonJS((exports) => {
|
|
|
12320
12320
|
}
|
|
12321
12321
|
var hasNativeCrypto$1 = (() => {
|
|
12322
12322
|
try {
|
|
12323
|
-
|
|
12323
|
+
createHash28("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 = createHash28("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 = createHash28("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
|
+
createHash28("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)) : createHash28("sha256");
|
|
12673
12673
|
}
|
|
12674
12674
|
};
|
|
12675
12675
|
}
|
|
@@ -13334,7 +13334,7 @@ var require_event_streams = __commonJS((exports) => {
|
|
|
13334
13334
|
streamEnded = true;
|
|
13335
13335
|
});
|
|
13336
13336
|
while (!generationEnded) {
|
|
13337
|
-
const value = await new Promise((
|
|
13337
|
+
const value = await new Promise((resolve24) => setTimeout(() => resolve24(records.shift()), 0));
|
|
13338
13338
|
if (value) {
|
|
13339
13339
|
yield value;
|
|
13340
13340
|
}
|
|
@@ -14542,8 +14542,8 @@ var require_protocols = __commonJS((exports) => {
|
|
|
14542
14542
|
fields2.forEach(this.setField.bind(this));
|
|
14543
14543
|
this.encoding = encoding;
|
|
14544
14544
|
}
|
|
14545
|
-
setField(
|
|
14546
|
-
this.entries[
|
|
14545
|
+
setField(field3) {
|
|
14546
|
+
this.entries[field3.name.toLowerCase()] = field3;
|
|
14547
14547
|
}
|
|
14548
14548
|
getField(name) {
|
|
14549
14549
|
return this.entries[name.toLowerCase()];
|
|
@@ -14552,7 +14552,7 @@ var require_protocols = __commonJS((exports) => {
|
|
|
14552
14552
|
delete this.entries[name.toLowerCase()];
|
|
14553
14553
|
}
|
|
14554
14554
|
getByType(kind) {
|
|
14555
|
-
return Object.values(this.entries).filter((
|
|
14555
|
+
return Object.values(this.entries).filter((field3) => field3.kind === kind);
|
|
14556
14556
|
}
|
|
14557
14557
|
}
|
|
14558
14558
|
var getHttpHandlerExtensionConfiguration = (runtimeConfig) => {
|
|
@@ -14852,7 +14852,7 @@ var require_retry = __commonJS((exports) => {
|
|
|
14852
14852
|
}
|
|
14853
14853
|
};
|
|
14854
14854
|
}
|
|
14855
|
-
var cooldown = (ms) => new Promise((
|
|
14855
|
+
var cooldown = (ms) => new Promise((resolve24) => setTimeout(resolve24, ms));
|
|
14856
14856
|
var isRetryStrategyV2 = (retryStrategy) => typeof retryStrategy.acquireInitialRetryToken !== "undefined" && typeof retryStrategy.refreshRetryTokenForRetry !== "undefined" && typeof retryStrategy.recordSuccess !== "undefined";
|
|
14857
14857
|
var getRetryErrorInfo = (error, logger) => {
|
|
14858
14858
|
const errorInfo = {
|
|
@@ -14951,7 +14951,7 @@ var require_retry = __commonJS((exports) => {
|
|
|
14951
14951
|
this.refillTokenBucket();
|
|
14952
14952
|
while (amount > this.availableTokens) {
|
|
14953
14953
|
const delay = (amount - this.availableTokens) / this.fillRate * 1000;
|
|
14954
|
-
await new Promise((
|
|
14954
|
+
await new Promise((resolve24) => DefaultRateLimiter.setTimeoutFn(resolve24, delay));
|
|
14955
14955
|
this.refillTokenBucket();
|
|
14956
14956
|
}
|
|
14957
14957
|
this.availableTokens = this.availableTokens - amount;
|
|
@@ -15293,7 +15293,7 @@ var require_retry = __commonJS((exports) => {
|
|
|
15293
15293
|
const delayFromResponse = getDelayFromRetryAfterHeader(err.$response);
|
|
15294
15294
|
const delay = Math.max(delayFromResponse || 0, delayFromDecider);
|
|
15295
15295
|
totalDelay += delay;
|
|
15296
|
-
await new Promise((
|
|
15296
|
+
await new Promise((resolve24) => setTimeout(resolve24, delay));
|
|
15297
15297
|
continue;
|
|
15298
15298
|
}
|
|
15299
15299
|
if (!err.$metadata) {
|
|
@@ -18166,7 +18166,7 @@ ${toHex(hashedRequest)}`;
|
|
|
18166
18166
|
return hash2.digest();
|
|
18167
18167
|
};
|
|
18168
18168
|
var getCanonicalHeaders = ({ headers }, unsignableHeaders, signableHeaders) => {
|
|
18169
|
-
const
|
|
18169
|
+
const canonical8 = {};
|
|
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
|
+
canonical8[canonicalHeaderName] = headers[headerName].trim().replace(/\s+/g, " ");
|
|
18181
18181
|
}
|
|
18182
|
-
return
|
|
18182
|
+
return canonical8;
|
|
18183
18183
|
};
|
|
18184
18184
|
var getPayloadHash = async ({ headers, body }, hashConstructor) => {
|
|
18185
18185
|
for (const headerName in headers) {
|
|
@@ -20175,7 +20175,7 @@ var require_cbor = __commonJS((exports) => {
|
|
|
20175
20175
|
const { memberSchemas, encodedKeys, memberNames } = cache;
|
|
20176
20176
|
const z = encodedKeys.length;
|
|
20177
20177
|
const result = {};
|
|
20178
|
-
let
|
|
20178
|
+
let unknownKey2;
|
|
20179
20179
|
let unknownValue;
|
|
20180
20180
|
let unknownCount = 0;
|
|
20181
20181
|
let hasType = false;
|
|
@@ -20197,7 +20197,7 @@ var require_cbor = __commonJS((exports) => {
|
|
|
20197
20197
|
if (key === "__type" && typeof val === "string") {
|
|
20198
20198
|
hasType = true;
|
|
20199
20199
|
} else {
|
|
20200
|
-
|
|
20200
|
+
unknownKey2 = key;
|
|
20201
20201
|
unknownValue = val;
|
|
20202
20202
|
++unknownCount;
|
|
20203
20203
|
}
|
|
@@ -20212,7 +20212,7 @@ var require_cbor = __commonJS((exports) => {
|
|
|
20212
20212
|
break;
|
|
20213
20213
|
}
|
|
20214
20214
|
if (resultEmpty && unknownCount === 1) {
|
|
20215
|
-
result.$unknown = [
|
|
20215
|
+
result.$unknown = [unknownKey2, unknownValue];
|
|
20216
20216
|
}
|
|
20217
20217
|
} else if (hasType) {
|
|
20218
20218
|
pos = startPos;
|
|
@@ -20360,7 +20360,7 @@ var require_cbor = __commonJS((exports) => {
|
|
|
20360
20360
|
const z = encodedKeys.length;
|
|
20361
20361
|
const isUnion = ns.isUnionSchema();
|
|
20362
20362
|
const result = {};
|
|
20363
|
-
let
|
|
20363
|
+
let unknownKey2;
|
|
20364
20364
|
let unknownValue;
|
|
20365
20365
|
let unknownCount = 0;
|
|
20366
20366
|
let hint = 0;
|
|
@@ -20376,7 +20376,7 @@ var require_cbor = __commonJS((exports) => {
|
|
|
20376
20376
|
break;
|
|
20377
20377
|
}
|
|
20378
20378
|
if (resultEmpty && unknownCount === 1) {
|
|
20379
|
-
result.$unknown = [
|
|
20379
|
+
result.$unknown = [unknownKey2, unknownValue];
|
|
20380
20380
|
}
|
|
20381
20381
|
}
|
|
20382
20382
|
return result;
|
|
@@ -20395,7 +20395,7 @@ var require_cbor = __commonJS((exports) => {
|
|
|
20395
20395
|
const key = readUtf8String();
|
|
20396
20396
|
const val = readValue(NormalizedSchema.of(15));
|
|
20397
20397
|
if (key !== "__type") {
|
|
20398
|
-
|
|
20398
|
+
unknownKey2 = key;
|
|
20399
20399
|
unknownValue = val;
|
|
20400
20400
|
++unknownCount;
|
|
20401
20401
|
}
|
|
@@ -21110,8 +21110,8 @@ var require_dist_cjs5 = __commonJS((exports) => {
|
|
|
21110
21110
|
this.attributes[name] = value;
|
|
21111
21111
|
return this;
|
|
21112
21112
|
}
|
|
21113
|
-
addChildNode(
|
|
21114
|
-
this.children.push(
|
|
21113
|
+
addChildNode(child2) {
|
|
21114
|
+
this.children.push(child2);
|
|
21115
21115
|
return this;
|
|
21116
21116
|
}
|
|
21117
21117
|
removeAttribute(name) {
|
|
@@ -21122,8 +21122,8 @@ var require_dist_cjs5 = __commonJS((exports) => {
|
|
|
21122
21122
|
this.name = name;
|
|
21123
21123
|
return this;
|
|
21124
21124
|
}
|
|
21125
|
-
c(
|
|
21126
|
-
this.children.push(
|
|
21125
|
+
c(child2) {
|
|
21126
|
+
this.children.push(child2);
|
|
21127
21127
|
return this;
|
|
21128
21128
|
}
|
|
21129
21129
|
a(name, value) {
|
|
@@ -21132,9 +21132,9 @@ var require_dist_cjs5 = __commonJS((exports) => {
|
|
|
21132
21132
|
}
|
|
21133
21133
|
return this;
|
|
21134
21134
|
}
|
|
21135
|
-
cc(input,
|
|
21136
|
-
if (input[
|
|
21137
|
-
const node = XmlNode.of(
|
|
21135
|
+
cc(input, field3, withName = field3) {
|
|
21136
|
+
if (input[field3] != null) {
|
|
21137
|
+
const node = XmlNode.of(field3, input[field3]).withName(withName);
|
|
21138
21138
|
this.c(node);
|
|
21139
21139
|
}
|
|
21140
21140
|
}
|
|
@@ -21240,10 +21240,10 @@ var require_dist_cjs5 = __commonJS((exports) => {
|
|
|
21240
21240
|
}
|
|
21241
21241
|
readAttrValue() {
|
|
21242
21242
|
const p = this;
|
|
21243
|
-
const
|
|
21243
|
+
const quote3 = p.x[p.i];
|
|
21244
21244
|
++p.i;
|
|
21245
21245
|
let value = "";
|
|
21246
|
-
while (p.i < p.z && p.x[p.i] !==
|
|
21246
|
+
while (p.i < p.z && p.x[p.i] !== quote3) {
|
|
21247
21247
|
value += p.x[p.i++];
|
|
21248
21248
|
}
|
|
21249
21249
|
++p.i;
|
|
@@ -21350,18 +21350,18 @@ var require_dist_cjs5 = __commonJS((exports) => {
|
|
|
21350
21350
|
}
|
|
21351
21351
|
obj["#text"] = "#text" in obj ? obj["#text"] + text2 : text2;
|
|
21352
21352
|
}
|
|
21353
|
-
for (const
|
|
21354
|
-
if (
|
|
21353
|
+
for (const child2 of childTags) {
|
|
21354
|
+
if (child2.tag === "__proto__") {
|
|
21355
21355
|
writeKey(obj);
|
|
21356
21356
|
}
|
|
21357
|
-
if (
|
|
21358
|
-
if (Array.isArray(obj[
|
|
21359
|
-
obj[
|
|
21357
|
+
if (child2.tag in obj) {
|
|
21358
|
+
if (Array.isArray(obj[child2.tag])) {
|
|
21359
|
+
obj[child2.tag].push(child2.value);
|
|
21360
21360
|
} else {
|
|
21361
|
-
obj[
|
|
21361
|
+
obj[child2.tag] = [obj[child2.tag], child2.value];
|
|
21362
21362
|
}
|
|
21363
21363
|
} else {
|
|
21364
|
-
obj[
|
|
21364
|
+
obj[child2.tag] = child2.value;
|
|
21365
21365
|
}
|
|
21366
21366
|
}
|
|
21367
21367
|
for (const [k, v] of Object.entries(attrs)) {
|
|
@@ -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 canonical8 = String(value);
|
|
21704
|
+
if (normalized === canonical8) {
|
|
21705
21705
|
return true;
|
|
21706
21706
|
}
|
|
21707
|
-
if (/[eE]/.test(
|
|
21708
|
-
return normalized === expandToDecimal(
|
|
21707
|
+
if (/[eE]/.test(canonical8)) {
|
|
21708
|
+
return normalized === expandToDecimal(canonical8);
|
|
21709
21709
|
}
|
|
21710
21710
|
return false;
|
|
21711
21711
|
}
|
|
@@ -24646,7 +24646,7 @@ var init_node_http = () => {};
|
|
|
24646
24646
|
|
|
24647
24647
|
// node_modules/@smithy/credential-provider-imds/dist-es/remoteProvider/httpRequest.js
|
|
24648
24648
|
function httpRequest(options) {
|
|
24649
|
-
return new Promise((
|
|
24649
|
+
return new Promise((resolve24, reject) => {
|
|
24650
24650
|
const req = node_http.request({
|
|
24651
24651
|
method: "GET",
|
|
24652
24652
|
...options,
|
|
@@ -24671,7 +24671,7 @@ function httpRequest(options) {
|
|
|
24671
24671
|
chunks.push(chunk);
|
|
24672
24672
|
});
|
|
24673
24673
|
res.on("end", () => {
|
|
24674
|
-
|
|
24674
|
+
resolve24(Buffer.concat(chunks));
|
|
24675
24675
|
req.destroy();
|
|
24676
24676
|
});
|
|
24677
24677
|
});
|
|
@@ -25036,15 +25036,15 @@ var require_dist_cjs6 = __commonJS((exports) => {
|
|
|
25036
25036
|
var { Readable: Readable2 } = __require("stream");
|
|
25037
25037
|
var http2 = __require("http2");
|
|
25038
25038
|
function buildAbortError(abortSignal) {
|
|
25039
|
-
const
|
|
25040
|
-
if (
|
|
25041
|
-
if (
|
|
25039
|
+
const reason2 = abortSignal && typeof abortSignal === "object" && "reason" in abortSignal ? abortSignal.reason : undefined;
|
|
25040
|
+
if (reason2) {
|
|
25041
|
+
if (reason2 instanceof Error) {
|
|
25042
25042
|
const abortError3 = new Error("Request aborted");
|
|
25043
25043
|
abortError3.name = "AbortError";
|
|
25044
|
-
abortError3.cause =
|
|
25044
|
+
abortError3.cause = reason2;
|
|
25045
25045
|
return abortError3;
|
|
25046
25046
|
}
|
|
25047
|
-
const abortError2 = new Error(String(
|
|
25047
|
+
const abortError2 = new Error(String(reason2));
|
|
25048
25048
|
abortError2.name = "AbortError";
|
|
25049
25049
|
return abortError2;
|
|
25050
25050
|
}
|
|
@@ -25168,21 +25168,21 @@ var require_dist_cjs6 = __commonJS((exports) => {
|
|
|
25168
25168
|
let sendBody = true;
|
|
25169
25169
|
if (!externalAgent && expect === "100-continue") {
|
|
25170
25170
|
sendBody = await Promise.race([
|
|
25171
|
-
new Promise((
|
|
25172
|
-
timeoutId = Number(timing.setTimeout(() =>
|
|
25171
|
+
new Promise((resolve24) => {
|
|
25172
|
+
timeoutId = Number(timing.setTimeout(() => resolve24(true), Math.max(MIN_WAIT_TIME, maxContinueTimeoutMs)));
|
|
25173
25173
|
}),
|
|
25174
|
-
new Promise((
|
|
25174
|
+
new Promise((resolve24) => {
|
|
25175
25175
|
httpRequest2.on("continue", () => {
|
|
25176
25176
|
timing.clearTimeout(timeoutId);
|
|
25177
|
-
|
|
25177
|
+
resolve24(true);
|
|
25178
25178
|
});
|
|
25179
25179
|
httpRequest2.on("response", () => {
|
|
25180
25180
|
timing.clearTimeout(timeoutId);
|
|
25181
|
-
|
|
25181
|
+
resolve24(false);
|
|
25182
25182
|
});
|
|
25183
25183
|
httpRequest2.on("error", () => {
|
|
25184
25184
|
timing.clearTimeout(timeoutId);
|
|
25185
|
-
|
|
25185
|
+
resolve24(false);
|
|
25186
25186
|
});
|
|
25187
25187
|
})
|
|
25188
25188
|
]);
|
|
@@ -25198,8 +25198,8 @@ var require_dist_cjs6 = __commonJS((exports) => {
|
|
|
25198
25198
|
}
|
|
25199
25199
|
if (body) {
|
|
25200
25200
|
const isBuffer = Buffer.isBuffer(body);
|
|
25201
|
-
const
|
|
25202
|
-
if (isBuffer ||
|
|
25201
|
+
const isString2 = typeof body === "string";
|
|
25202
|
+
if (isBuffer || isString2) {
|
|
25203
25203
|
if (isBuffer && body.byteLength === 0) {
|
|
25204
25204
|
httpRequest2.end();
|
|
25205
25205
|
} else {
|
|
@@ -25259,13 +25259,13 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
|
|
|
25259
25259
|
return socketWarningTimestamp;
|
|
25260
25260
|
}
|
|
25261
25261
|
constructor(options) {
|
|
25262
|
-
this.configProvider = new Promise((
|
|
25262
|
+
this.configProvider = new Promise((resolve24, reject) => {
|
|
25263
25263
|
if (typeof options === "function") {
|
|
25264
25264
|
options().then((_options) => {
|
|
25265
|
-
|
|
25265
|
+
resolve24(this.resolveDefaultConfig(_options));
|
|
25266
25266
|
}).catch(reject);
|
|
25267
25267
|
} else {
|
|
25268
|
-
|
|
25268
|
+
resolve24(this.resolveDefaultConfig(options));
|
|
25269
25269
|
}
|
|
25270
25270
|
});
|
|
25271
25271
|
}
|
|
@@ -25297,7 +25297,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
|
|
|
25297
25297
|
timing.clearTimeout(socketTimeoutId);
|
|
25298
25298
|
timing.clearTimeout(keepAliveTimeoutId);
|
|
25299
25299
|
};
|
|
25300
|
-
const
|
|
25300
|
+
const resolve24 = async (arg) => {
|
|
25301
25301
|
await writeRequestBodyPromise;
|
|
25302
25302
|
clearTimeouts();
|
|
25303
25303
|
_resolve(arg);
|
|
@@ -25361,7 +25361,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
|
|
|
25361
25361
|
headers: getTransformedHeaders(res.headers),
|
|
25362
25362
|
body: res
|
|
25363
25363
|
});
|
|
25364
|
-
|
|
25364
|
+
resolve24({ response: httpResponse });
|
|
25365
25365
|
});
|
|
25366
25366
|
req.on("error", (err) => {
|
|
25367
25367
|
if (NODEJS_TIMEOUT_ERROR_CODES.includes(err.code)) {
|
|
@@ -25693,13 +25693,13 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
|
|
|
25693
25693
|
return new NodeHttp2Handler(instanceOrOptions);
|
|
25694
25694
|
}
|
|
25695
25695
|
constructor(options) {
|
|
25696
|
-
this.configProvider = new Promise((
|
|
25696
|
+
this.configProvider = new Promise((resolve24, reject) => {
|
|
25697
25697
|
if (typeof options === "function") {
|
|
25698
25698
|
options().then((opts) => {
|
|
25699
|
-
|
|
25699
|
+
resolve24(opts || {});
|
|
25700
25700
|
}).catch(reject);
|
|
25701
25701
|
} else {
|
|
25702
|
-
|
|
25702
|
+
resolve24(options || {});
|
|
25703
25703
|
}
|
|
25704
25704
|
});
|
|
25705
25705
|
}
|
|
@@ -25724,7 +25724,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
|
|
|
25724
25724
|
return new Promise((_resolve, _reject) => {
|
|
25725
25725
|
let fulfilled = false;
|
|
25726
25726
|
let writeRequestBodyPromise = undefined;
|
|
25727
|
-
const
|
|
25727
|
+
const resolve24 = async (arg) => {
|
|
25728
25728
|
await writeRequestBodyPromise;
|
|
25729
25729
|
_resolve(arg);
|
|
25730
25730
|
};
|
|
@@ -25809,7 +25809,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
|
|
|
25809
25809
|
body: clientHttp2Stream
|
|
25810
25810
|
});
|
|
25811
25811
|
fulfilled = true;
|
|
25812
|
-
|
|
25812
|
+
resolve24({ response: httpResponse });
|
|
25813
25813
|
if (useIsolatedSession) {
|
|
25814
25814
|
session.close();
|
|
25815
25815
|
clientHttp2Stream.on("end", () => {
|
|
@@ -25942,7 +25942,7 @@ var retryWrapper = (toRetry, maxRetries, delayMs) => {
|
|
|
25942
25942
|
try {
|
|
25943
25943
|
return await toRetry();
|
|
25944
25944
|
} catch (e3) {
|
|
25945
|
-
await new Promise((
|
|
25945
|
+
await new Promise((resolve24) => setTimeout(resolve24, delayMs));
|
|
25946
25946
|
}
|
|
25947
25947
|
}
|
|
25948
25948
|
return await toRetry();
|
|
@@ -29443,10 +29443,10 @@ 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 createHash28, createPrivateKey, createPublicKey, sign } from "crypto";
|
|
29447
29447
|
import { promises as fs2 } from "fs";
|
|
29448
29448
|
import { homedir as homedir7 } from "os";
|
|
29449
|
-
import { dirname as
|
|
29449
|
+
import { dirname as dirname24, join as join38 } from "path";
|
|
29450
29450
|
var import_config28, import_protocols3, LoginCredentialsFetcher;
|
|
29451
29451
|
var init_LoginCredentialsFetcher = __esm(() => {
|
|
29452
29452
|
import_config28 = __toESM(require_config(), 1);
|
|
@@ -29606,7 +29606,7 @@ var init_LoginCredentialsFetcher = __esm(() => {
|
|
|
29606
29606
|
}
|
|
29607
29607
|
async saveToken(token) {
|
|
29608
29608
|
const tokenFilePath = this.getTokenFilePath();
|
|
29609
|
-
const directory =
|
|
29609
|
+
const directory = dirname24(tokenFilePath);
|
|
29610
29610
|
try {
|
|
29611
29611
|
await fs2.mkdir(directory, { recursive: true });
|
|
29612
29612
|
} catch (error) {}
|
|
@@ -29615,7 +29615,7 @@ var init_LoginCredentialsFetcher = __esm(() => {
|
|
|
29615
29615
|
getTokenFilePath() {
|
|
29616
29616
|
const directory = process.env.AWS_LOGIN_CACHE_DIRECTORY ?? join38(homedir7(), ".aws", "login", "cache");
|
|
29617
29617
|
const loginSessionBytes = Buffer.from(this.loginSession, "utf8");
|
|
29618
|
-
const loginSessionSha256 =
|
|
29618
|
+
const loginSessionSha256 = createHash28("sha256").update(loginSessionBytes).digest("hex");
|
|
29619
29619
|
return join38(directory, `${loginSessionSha256}.json`);
|
|
29620
29620
|
}
|
|
29621
29621
|
derToRawSignature(derSignature) {
|
|
@@ -31067,7 +31067,7 @@ import { existsSync as existsSync22 } from "fs";
|
|
|
31067
31067
|
import { join as join210 } from "path";
|
|
31068
31068
|
import { existsSync as existsSync17 } from "fs";
|
|
31069
31069
|
import { homedir as homedir8 } from "os";
|
|
31070
|
-
import { join as join42, resolve as
|
|
31070
|
+
import { join as join42, resolve as resolve24 } from "path";
|
|
31071
31071
|
import { homedir as pathsResolverHomedir2 } from "os";
|
|
31072
31072
|
import { join as pathsResolverJoin2 } from "path";
|
|
31073
31073
|
import { createHmac as createHmac4, timingSafeEqual as timingSafeEqual3 } from "crypto";
|
|
@@ -31251,9 +31251,9 @@ function exactEventsHome() {
|
|
|
31251
31251
|
function getEventsHome() {
|
|
31252
31252
|
const exact = exactEventsHome();
|
|
31253
31253
|
if (exact)
|
|
31254
|
-
return
|
|
31254
|
+
return resolve24(exact);
|
|
31255
31255
|
const resolved = resolverHome();
|
|
31256
|
-
return adoptResolverHome(resolved) ?
|
|
31256
|
+
return adoptResolverHome(resolved) ? resolve24(resolved) : resolve24(legacyHomeDir());
|
|
31257
31257
|
}
|
|
31258
31258
|
function getEventsDataDir(override) {
|
|
31259
31259
|
return override || getEventsHome();
|
|
@@ -31793,7 +31793,7 @@ async function pinnedNativeRequest(target, addresses, method, headers, body4, si
|
|
|
31793
31793
|
callback(null, entries);
|
|
31794
31794
|
}
|
|
31795
31795
|
};
|
|
31796
|
-
return new Promise((
|
|
31796
|
+
return new Promise((resolve25, reject) => {
|
|
31797
31797
|
const request2 = isHttps ? nodeHttpsRequest(requestOptions, onResponse) : nodeHttpRequest(requestOptions, onResponse);
|
|
31798
31798
|
const onAbort = () => {
|
|
31799
31799
|
const error = new Error("The operation was aborted.");
|
|
@@ -31820,7 +31820,7 @@ async function pinnedNativeRequest(target, addresses, method, headers, body4, si
|
|
|
31820
31820
|
else if (Array.isArray(value))
|
|
31821
31821
|
headersRecord[name] = value.join(", ");
|
|
31822
31822
|
}
|
|
31823
|
-
|
|
31823
|
+
resolve25(new Response(Buffer.concat(chunks), { status: response.statusCode ?? 200, headers: headersRecord }));
|
|
31824
31824
|
});
|
|
31825
31825
|
}
|
|
31826
31826
|
});
|
|
@@ -31917,25 +31917,25 @@ async function dispatchCommand(event, channel) {
|
|
|
31917
31917
|
HASNA_EVENT_SCHEMA_VERSION: event.schemaVersion,
|
|
31918
31918
|
HASNA_EVENT_JSON: eventJson
|
|
31919
31919
|
};
|
|
31920
|
-
return new Promise((
|
|
31921
|
-
const
|
|
31920
|
+
return new Promise((resolve25) => {
|
|
31921
|
+
const child2 = spawn3(channel.command.command, channel.command.args ?? [], {
|
|
31922
31922
|
cwd: channel.command.cwd,
|
|
31923
31923
|
env,
|
|
31924
31924
|
stdio: ["pipe", "pipe", "pipe"]
|
|
31925
31925
|
});
|
|
31926
31926
|
let stdout = "";
|
|
31927
31927
|
let stderr = "";
|
|
31928
|
-
const timeout = setTimeout(() =>
|
|
31929
|
-
|
|
31930
|
-
|
|
31928
|
+
const timeout = setTimeout(() => child2.kill("SIGTERM"), channel.command.timeoutMs ?? 15000);
|
|
31929
|
+
child2.stdin.end(eventJson);
|
|
31930
|
+
child2.stdout.on("data", (chunk) => {
|
|
31931
31931
|
stdout += chunk.toString();
|
|
31932
31932
|
});
|
|
31933
|
-
|
|
31933
|
+
child2.stderr.on("data", (chunk) => {
|
|
31934
31934
|
stderr += chunk.toString();
|
|
31935
31935
|
});
|
|
31936
|
-
|
|
31936
|
+
child2.on("error", (error) => {
|
|
31937
31937
|
clearTimeout(timeout);
|
|
31938
|
-
|
|
31938
|
+
resolve25({
|
|
31939
31939
|
attempt: 1,
|
|
31940
31940
|
status: "failed",
|
|
31941
31941
|
startedAt,
|
|
@@ -31945,10 +31945,10 @@ async function dispatchCommand(event, channel) {
|
|
|
31945
31945
|
error: error.message
|
|
31946
31946
|
});
|
|
31947
31947
|
});
|
|
31948
|
-
|
|
31948
|
+
child2.on("close", (code, signal) => {
|
|
31949
31949
|
clearTimeout(timeout);
|
|
31950
31950
|
const success = code === 0;
|
|
31951
|
-
|
|
31951
|
+
resolve25({
|
|
31952
31952
|
attempt: 1,
|
|
31953
31953
|
status: success ? "success" : "failed",
|
|
31954
31954
|
startedAt,
|
|
@@ -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.52",
|
|
32377
32377
|
description: "Skills library for AI coding agents",
|
|
32378
32378
|
type: "module",
|
|
32379
32379
|
bin: {
|
|
@@ -34672,7 +34672,14 @@ async function inspectSkillBundle(bundle, options = {}) {
|
|
|
34672
34672
|
decoder.destroy(terminalError);
|
|
34673
34673
|
};
|
|
34674
34674
|
const onAbort = () => stop("BUNDLE_ABORTED");
|
|
34675
|
-
const
|
|
34675
|
+
const expire = () => {
|
|
34676
|
+
const remaining = deadline - performance.now();
|
|
34677
|
+
if (remaining > 0)
|
|
34678
|
+
timer = setTimeout(expire, Math.max(1, Math.ceil(remaining)));
|
|
34679
|
+
else
|
|
34680
|
+
stop("BUNDLE_TIMEOUT");
|
|
34681
|
+
};
|
|
34682
|
+
let timer = setTimeout(expire, Math.max(1, Math.ceil(deadline - performance.now())));
|
|
34676
34683
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
34677
34684
|
let decompressedByteSize = 0;
|
|
34678
34685
|
let bytesSinceYield = 0;
|
|
@@ -34916,8 +34923,8 @@ function profileSelectionSnapshot(selections) {
|
|
|
34916
34923
|
// src/lib/selection-cache.ts
|
|
34917
34924
|
class SkillSelectionError extends Error {
|
|
34918
34925
|
code;
|
|
34919
|
-
constructor(code, message) {
|
|
34920
|
-
super(message);
|
|
34926
|
+
constructor(code, message, options) {
|
|
34927
|
+
super(message, options);
|
|
34921
34928
|
this.code = code;
|
|
34922
34929
|
this.name = "SkillSelectionError";
|
|
34923
34930
|
}
|
|
@@ -35051,8 +35058,8 @@ function atomicWrite(path, bytes, mode, durable = false) {
|
|
|
35051
35058
|
}
|
|
35052
35059
|
}
|
|
35053
35060
|
}
|
|
35054
|
-
function readSelectionJson(path) {
|
|
35055
|
-
const bytes = readRegularFile(path, MAX_PROFILE_DOCUMENT_BYTES);
|
|
35061
|
+
function readSelectionJson(path, maximumBytes = MAX_PROFILE_DOCUMENT_BYTES) {
|
|
35062
|
+
const bytes = readRegularFile(path, Math.min(maximumBytes, MAX_PROFILE_DOCUMENT_BYTES));
|
|
35056
35063
|
if (!bytes)
|
|
35057
35064
|
return null;
|
|
35058
35065
|
try {
|
|
@@ -35064,10 +35071,10 @@ function readSelectionJson(path) {
|
|
|
35064
35071
|
async function verifiedEntries(selection, bytes, signal, deadline) {
|
|
35065
35072
|
if (`sha256:${sha256Hex(bytes)}` !== selection.bundleDigest)
|
|
35066
35073
|
throw new SkillSelectionError("BUNDLE_DIGEST_MISMATCH", "The skill bundle does not match its selected digest.");
|
|
35067
|
-
const remaining = deadline === undefined ? undefined : Math.
|
|
35074
|
+
const remaining = deadline === undefined ? undefined : Math.ceil(deadline - performance.now());
|
|
35068
35075
|
signal?.throwIfAborted();
|
|
35069
35076
|
if (remaining !== undefined && remaining <= 0)
|
|
35070
|
-
throw new
|
|
35077
|
+
throw new SkillBundleInspectionError("BUNDLE_TIMEOUT", "Bundle inspection deadline exceeded");
|
|
35071
35078
|
const bundle = await inspectSkillBundle(bytes, { signal, ...remaining === undefined ? {} : { limits: { timeoutMs: remaining } } });
|
|
35072
35079
|
return bundle.entries;
|
|
35073
35080
|
}
|
|
@@ -37311,6 +37318,10 @@ function identifier2(value) {
|
|
|
37311
37318
|
function invalid2() {
|
|
37312
37319
|
throw new Error("The Skills API returned an invalid profile response");
|
|
37313
37320
|
}
|
|
37321
|
+
function unavailable(error, message) {
|
|
37322
|
+
const name = error?.name;
|
|
37323
|
+
return new SkillSelectionError("SKILLS_API_UNAVAILABLE", message, name === "AbortError" || name === "TimeoutError" ? { cause: new DOMException("The Skills API request was cut short", name) } : undefined);
|
|
37324
|
+
}
|
|
37314
37325
|
function validateSelection2(value) {
|
|
37315
37326
|
if (!object(value) || !identifier2(value.slug) || typeof value.version !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/.test(value.version) || value.version.includes("..") || typeof value.bundleDigest !== "string" || !/^sha256:[a-f0-9]{64}$/.test(value.bundleDigest))
|
|
37316
37327
|
invalid2();
|
|
@@ -37358,8 +37369,8 @@ class HttpProfileClient {
|
|
|
37358
37369
|
...init.headers
|
|
37359
37370
|
}
|
|
37360
37371
|
});
|
|
37361
|
-
} catch {
|
|
37362
|
-
throw
|
|
37372
|
+
} catch (error) {
|
|
37373
|
+
throw unavailable(error, "Unable to reach the configured Skills API");
|
|
37363
37374
|
}
|
|
37364
37375
|
if (!response.ok) {
|
|
37365
37376
|
response.body?.cancel().catch(() => {});
|
|
@@ -37376,7 +37387,9 @@ class HttpProfileClient {
|
|
|
37376
37387
|
async read(response, limit = MAX_PROFILE_DOCUMENT_BYTES) {
|
|
37377
37388
|
try {
|
|
37378
37389
|
return JSON.parse(new TextDecoder().decode(await readBoundedResponse(response, limit, this.signal)));
|
|
37379
|
-
} catch {
|
|
37390
|
+
} catch (error) {
|
|
37391
|
+
if (this.signal?.aborted)
|
|
37392
|
+
throw unavailable(this.signal.reason ?? error, "The Skills API response was cut short");
|
|
37380
37393
|
invalid2();
|
|
37381
37394
|
}
|
|
37382
37395
|
}
|
|
@@ -37493,6 +37506,8 @@ function inspectSkillSession(sessionId, options = {}) {
|
|
|
37493
37506
|
loadedCount: receipt.loaded.length
|
|
37494
37507
|
};
|
|
37495
37508
|
}
|
|
37509
|
+
var SESSION_RENEWAL_REFUSAL_TTL_MS = 5 * 60 * 1000;
|
|
37510
|
+
var SESSION_RENEWAL_REFUSAL_MAX_BYTES = 4 * 1024;
|
|
37496
37511
|
async function reconcileSkillSession(input, options = {}) {
|
|
37497
37512
|
if (![input.fromProfile, input.fromRevision, input.selectionProfile, input.profileRevision].every((value) => typeof value === "string" && value.trim()) || !/^[a-f0-9]{64}$/.test(input.receiptSha256)) {
|
|
37498
37513
|
throw new SkillSelectionError("INVALID_SESSION_RECONCILIATION", "Name the exact old receipt SHA256, old profile/revision and intended target profile/revision.");
|
|
@@ -37554,10 +37569,10 @@ async function reconcileSkillSession(input, options = {}) {
|
|
|
37554
37569
|
return { applied: true, plan, planDigest, ...result };
|
|
37555
37570
|
}
|
|
37556
37571
|
// src/lib/selected-run.ts
|
|
37557
|
-
import { createHash as
|
|
37572
|
+
import { createHash as createHash27 } from "crypto";
|
|
37558
37573
|
import { spawn as spawn2 } from "child_process";
|
|
37559
37574
|
import { mkdirSync as mkdirSync11, mkdtempSync as mkdtempSync3, writeFileSync as writeFileSync10, realpathSync as realpathSync15 } from "fs";
|
|
37560
|
-
import { dirname as
|
|
37575
|
+
import { dirname as dirname23, join as join37, resolve as resolve23 } from "path";
|
|
37561
37576
|
import { tmpdir, hostname as stationHostname2 } from "os";
|
|
37562
37577
|
|
|
37563
37578
|
// src/lib/dependency-preparation.ts
|
|
@@ -37952,7 +37967,7 @@ import {
|
|
|
37952
37967
|
writeFileSync as writeFileSync8
|
|
37953
37968
|
} from "fs";
|
|
37954
37969
|
import { homedir as homedir5 } from "os";
|
|
37955
|
-
import { basename as
|
|
37970
|
+
import { basename as basename13, dirname as dirname22, join as join32 } from "path";
|
|
37956
37971
|
|
|
37957
37972
|
// src/lib/sumi-settings-witness.ts
|
|
37958
37973
|
import { createHash as createHash7 } from "crypto";
|
|
@@ -38089,6 +38104,10 @@ function parse2(text) {
|
|
|
38089
38104
|
need(root.entries.length <= CLAUDE_SETTINGS_WITNESS_LIMITS.rows, "exceeds its settings field limit");
|
|
38090
38105
|
return root;
|
|
38091
38106
|
}
|
|
38107
|
+
function parseNativeJsonObject(text) {
|
|
38108
|
+
need(typeof text === "string" && Buffer.byteLength(text) <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes, "exceeds its byte limit");
|
|
38109
|
+
return parse2(text);
|
|
38110
|
+
}
|
|
38092
38111
|
var BOOLEAN_PREFERENCES = new Set([
|
|
38093
38112
|
"autoScrollEnabled",
|
|
38094
38113
|
"axScreenReader",
|
|
@@ -38426,7 +38445,8 @@ var MEASURED_CODEX_CAPABILITIES = {
|
|
|
38426
38445
|
"codex-cli 0.158.0": ["hooks"],
|
|
38427
38446
|
"codex-cli 0.159.0": ["hooks"],
|
|
38428
38447
|
"codex-cli 0.159.2": ["hooks", "qualified-skill-catalog"],
|
|
38429
|
-
"codex-cli 0.160.0": ["hooks", "qualified-skill-catalog"]
|
|
38448
|
+
"codex-cli 0.160.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
38449
|
+
"codex-cli 0.160.1": ["hooks", "qualified-skill-catalog", "installed-plugin-review"]
|
|
38430
38450
|
};
|
|
38431
38451
|
function supportsCodexNativeCapability(version, capability) {
|
|
38432
38452
|
return typeof version === "string" && Object.hasOwn(MEASURED_CODEX_CAPABILITIES, version) && MEASURED_CODEX_CAPABILITIES[version].includes(capability);
|
|
@@ -39027,6 +39047,7 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache, controls, read, rules)
|
|
|
39027
39047
|
function reviewCodexPluginControls(catalog, documents, cache, cwd, read, rules, pluginSettings, plannedRules, denials = []) {
|
|
39028
39048
|
if (!supportsCodexNativeCapability(catalog?.version, "qualified-skill-catalog") || catalog.cwd !== cwd)
|
|
39029
39049
|
refuse3();
|
|
39050
|
+
const installedPluginReview = supportsCodexNativeCapability(catalog.version, "installed-plugin-review");
|
|
39030
39051
|
if (!Array.isArray(denials) || denials.length > 4096 || new Set(denials.map((item) => item?.path)).size !== denials.length || denials.some((item) => !item || Object.keys(item).sort().join(",") !== "name,path,sha256" || typeof item.name !== "string" || typeof item.path !== "string" || !/^[a-f0-9]{64}$/.test(item.sha256)))
|
|
39031
39052
|
refuse3();
|
|
39032
39053
|
const usedDenials = new Set;
|
|
@@ -39058,7 +39079,7 @@ function reviewCodexPluginControls(catalog, documents, cache, cwd, read, rules,
|
|
|
39058
39079
|
if (listed.length > 1)
|
|
39059
39080
|
refuse3();
|
|
39060
39081
|
const installed = installedPlugins.filter((plugin) => plugin.id === expectedPluginId && plugin.name === pluginName);
|
|
39061
|
-
if (
|
|
39082
|
+
if (installedPluginReview && installed.length === 1 && installed[0].installed && installed[0].localVersion === basename4(located.root) && installed[0].sourceType === "local" && codexPluginSourceIsConfigControlled(installed[0])) {
|
|
39062
39083
|
const plugin = installed[0], input = { pluginId: expectedPluginId, namespace: located.namespace, pluginParent: located.pluginParent, sourceRoot: plugin.sourcePath, sourceSha256: plugin.sourceSha256 };
|
|
39063
39084
|
if (input.sourceRoot !== located.root && !input.sourceRoot.startsWith(cache + sep3) && (lstatSync7(input.sourceRoot, { throwIfNoEntry: false }) || documents.some((path) => path.startsWith(input.sourceRoot + sep3)))) {
|
|
39064
39085
|
if (skills.some((skill) => skill.path === input.sourceRoot || skill.path.startsWith(input.sourceRoot + sep3)) || !sourceInputUnchanged(input, cache, read))
|
|
@@ -39067,7 +39088,7 @@ function reviewCodexPluginControls(catalog, documents, cache, cwd, read, rules,
|
|
|
39067
39088
|
}
|
|
39068
39089
|
}
|
|
39069
39090
|
const settings = pluginSettings && typeof pluginSettings === "object" && !Array.isArray(pluginSettings) ? pluginSettings : undefined;
|
|
39070
|
-
if (
|
|
39091
|
+
if (installedPluginReview && !listed.length && !skills.some((skill) => skill.pluginId === expectedPluginId) && installed.length === 1 && installed[0].installed && !installed[0].enabled && codexPluginSourceIsConfigControlled(installed[0]) && settings && Object.hasOwn(settings, expectedPluginId) && settings[expectedPluginId]?.enabled === false) {
|
|
39071
39092
|
if (!Array.isArray(rules))
|
|
39072
39093
|
refuse3();
|
|
39073
39094
|
const exactPathDeny = rules.some((rule) => rule?.path === document && rule?.enabled === false);
|
|
@@ -39100,12 +39121,12 @@ function reviewCodexPluginControls(catalog, documents, cache, cwd, read, rules,
|
|
|
39100
39121
|
const exactPathDeny = Array.isArray(rules) && rules.some((rule) => rule?.path === document && rule?.enabled === false);
|
|
39101
39122
|
const nativeSkill = { name: parsed.name, path: document, pluginId: expectedPluginId, enabled: true };
|
|
39102
39123
|
const denial = denials.find((item) => item.path === document);
|
|
39103
|
-
const explicitDeny = denial !== undefined && remotePluginId !== undefined &&
|
|
39124
|
+
const explicitDeny = denial !== undefined && remotePluginId !== undefined && installedPluginReview && denial.name === parsed.name && denial.sha256 === createHash8("sha256").update(read(document)).digest("hex") && Array.isArray(rules) && !rules.some((rule) => (rule?.path === document || typeof rule?.name === "string" && rule.name.trim() === parsed.name) && rule.enabled !== false) && Array.isArray(plannedRules) && plannedRules.some((rule) => rule?.path === document && rule.enabled === false);
|
|
39104
39125
|
if (denial && !explicitDeny)
|
|
39105
39126
|
refuse3();
|
|
39106
39127
|
if (explicitDeny)
|
|
39107
39128
|
usedDenials.add(document);
|
|
39108
|
-
const plannedPathDeny =
|
|
39129
|
+
const plannedPathDeny = installedPluginReview && remotePluginId !== undefined && Array.isArray(rules) && rules.some((rule) => typeof rule?.name === "string" && rule.name.trim() === parsed.name && rule.enabled === false) && !rules.some((rule) => (rule?.path === document || typeof rule?.name === "string" && rule.name.trim() === parsed.name) && rule.enabled !== false) && Array.isArray(plannedRules) && plannedRules.some((rule) => rule?.path === document && rule.enabled === false) && isCodexNativeSkillDisabled(nativeSkill, plannedRules);
|
|
39109
39130
|
if (!explicitDeny && (!exactPathDeny && !plannedPathDeny || !isCodexNativeSkillDisabled(nativeSkill, rules)))
|
|
39110
39131
|
refuse3();
|
|
39111
39132
|
}
|
|
@@ -40276,10 +40297,10 @@ var NATIVE_SKILL_ROOTS = [
|
|
|
40276
40297
|
];
|
|
40277
40298
|
|
|
40278
40299
|
// src/lib/agent-integration.ts
|
|
40279
|
-
import { createHash as
|
|
40300
|
+
import { createHash as createHash25, randomUUID as randomUUID4 } from "crypto";
|
|
40280
40301
|
import { isDeepStrictEqual as isDeepStrictEqual8 } from "util";
|
|
40281
|
-
import { existsSync as existsSync7, lstatSync as lstatSync23, statSync as statSync7, mkdirSync as mkdirSync6, readFileSync as readFileSync17, readdirSync as readdirSync8, opendirSync as opendirSync5, readlinkSync as
|
|
40282
|
-
import { dirname as
|
|
40302
|
+
import { existsSync as existsSync7, lstatSync as lstatSync23, statSync as statSync7, mkdirSync as mkdirSync6, readFileSync as readFileSync17, readdirSync as readdirSync8, opendirSync as opendirSync5, readlinkSync as readlinkSync7, realpathSync as realpathSync11, renameSync as renameSync4, rmdirSync as rmdirSync3, writeFileSync as writeFileSync5, unlinkSync as unlinkSync5, chmodSync, openSync as openSync18, closeSync as closeSync18, fsyncSync as fsyncSync6, fstatSync as fstatSync18, readSync as readSync12, constants as constants15, linkSync as linkSync3 } from "fs";
|
|
40303
|
+
import { dirname as dirname18, join as join27, resolve as resolve20, relative as relative5, isAbsolute as isAbsolute22, sep as sep7 } from "path";
|
|
40283
40304
|
import { homedir as homedir3 } from "os";
|
|
40284
40305
|
|
|
40285
40306
|
// src/lib/managed-policy.ts
|
|
@@ -40287,7 +40308,202 @@ import { closeSync as closeSync11, constants as constants8, fstatSync as fstatSy
|
|
|
40287
40308
|
import { join as join15 } from "path";
|
|
40288
40309
|
|
|
40289
40310
|
// src/lib/agent-policy-limits.ts
|
|
40290
|
-
import { basename as
|
|
40311
|
+
import { basename as basename6, isAbsolute as isAbsolute9, join as join14, resolve as resolve8, sep as sep4 } from "path";
|
|
40312
|
+
|
|
40313
|
+
// src/lib/claude-marketplace-entry-witness.ts
|
|
40314
|
+
import { createHash as createHash12 } from "crypto";
|
|
40315
|
+
import { basename as basename5, dirname as dirname8, isAbsolute as isAbsolute8, resolve as resolve7 } from "path";
|
|
40316
|
+
var CLAUDE_MARKETPLACE_ENTRY_HASH_MODE = "claude-marketplace-entry-v1";
|
|
40317
|
+
var DOMAIN = "hasna.skills.claude-marketplace-entry.v1\x00";
|
|
40318
|
+
var PATH_CHARACTERS = 4096;
|
|
40319
|
+
var NAME = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
40320
|
+
function need4(value, reason) {
|
|
40321
|
+
if (!value)
|
|
40322
|
+
throw new Error(`Claude marketplace entry witness ${reason}`);
|
|
40323
|
+
}
|
|
40324
|
+
var bounded = (key) => key.length > 64 ? `${key.slice(0, 64)}...` : key;
|
|
40325
|
+
var quote = (text) => JSON.stringify(text).replace(/[^\x20-\x7e]/g, (character) => `\\u${character.charCodeAt(0).toString(16).padStart(4, "0")}`);
|
|
40326
|
+
var child = (path, key) => path + (/^[A-Za-z0-9_$-]{1,64}$/.test(key) ? `.${key}` : `[${JSON.stringify(bounded(key))}]`);
|
|
40327
|
+
function unknownKey(selector, path, key) {
|
|
40328
|
+
throw new Error(path === null ? `${CLAUDE_MARKETPLACE_ENTRY_HASH_MODE}: unknown top-level key ${quote(bounded(key))} in ${selector.marketplace}` : `${CLAUDE_MARKETPLACE_ENTRY_HASH_MODE}: unknown key ${quote(child(path, key))} in ${selector.marketplace}`);
|
|
40329
|
+
}
|
|
40330
|
+
function knownKeys(object4, allowed, selector, path) {
|
|
40331
|
+
for (const [key] of object4.entries)
|
|
40332
|
+
if (!allowed.has(key))
|
|
40333
|
+
unknownKey(selector, path, key);
|
|
40334
|
+
}
|
|
40335
|
+
var reason = (error) => String(error?.message ?? error).replace(/^Claude settings witness /, "");
|
|
40336
|
+
var MARKETPLACE_KEYS = new Set(["$schema", "name", "owner", "plugins", "description", "version", "metadata", "forceRemoveDeletedPlugins", "allowCrossMarketplaceDependenciesOn", "renames"]);
|
|
40337
|
+
var MARKETPLACE_METADATA_KEYS = new Set(["description", "version", "pluginRoot"]);
|
|
40338
|
+
var ENTRY_BOUND_KEYS = new Set([
|
|
40339
|
+
"name",
|
|
40340
|
+
"source",
|
|
40341
|
+
"strict",
|
|
40342
|
+
"defaultEnabled",
|
|
40343
|
+
"dependencies",
|
|
40344
|
+
"relevance",
|
|
40345
|
+
"headers",
|
|
40346
|
+
"headersHelper",
|
|
40347
|
+
"settings",
|
|
40348
|
+
"userConfig",
|
|
40349
|
+
"types",
|
|
40350
|
+
"channels",
|
|
40351
|
+
"skills",
|
|
40352
|
+
"commands",
|
|
40353
|
+
"agents",
|
|
40354
|
+
"hooks",
|
|
40355
|
+
"mcpServers",
|
|
40356
|
+
"lspServers",
|
|
40357
|
+
"outputStyles",
|
|
40358
|
+
"workflows",
|
|
40359
|
+
"experimental",
|
|
40360
|
+
"themes",
|
|
40361
|
+
"monitors"
|
|
40362
|
+
]);
|
|
40363
|
+
var ENTRY_OMITTED_KEYS = new Set(["$schema", "description", "version", "author", "homepage", "repository", "license", "keywords", "category", "tags", "displayName", "metadata"]);
|
|
40364
|
+
var EXPERIMENTAL_KEYS = new Set(["themes", "monitors", "evals"]);
|
|
40365
|
+
var SOURCE_KEYS = Object.freeze({
|
|
40366
|
+
github: ["source", "repo", "ref", "sha"],
|
|
40367
|
+
url: ["source", "url", "ref", "sha", "path"],
|
|
40368
|
+
"git-subdir": ["source", "url", "path", "ref", "sha"],
|
|
40369
|
+
npm: ["source", "package", "version", "registry"],
|
|
40370
|
+
archive: ["source", "url", "sha256"],
|
|
40371
|
+
command: ["source", "command", "timeout", "mode"]
|
|
40372
|
+
});
|
|
40373
|
+
var field = (object4, key) => object4.entries.find(([name]) => name === key)?.[1];
|
|
40374
|
+
var isString = (value) => value?.kind === "string";
|
|
40375
|
+
var isBoolean = (value) => value?.kind === "literal" && (value.value === "true" || value.value === "false");
|
|
40376
|
+
var stringArray = (value) => value?.kind === "array" && value.items.every(isString);
|
|
40377
|
+
var stringObject = (value) => value?.kind === "object" && value.entries.every(([, item]) => isString(item));
|
|
40378
|
+
function claudeMarketplaceEntrySourceValid(source) {
|
|
40379
|
+
const path = source?.path;
|
|
40380
|
+
return typeof path === "string" && path.length > 0 && path.length <= PATH_CHARACTERS && !/[\x00-\x1f\x7f]/.test(path) && isAbsolute8(path) && resolve7(path) === path && basename5(path) === "marketplace.json" && basename5(dirname8(path)) === ".claude-plugin" && typeof source.marketplace === "string" && NAME.test(source.marketplace) && !source.marketplace.includes("..") && typeof source.plugin === "string" && NAME.test(source.plugin);
|
|
40381
|
+
}
|
|
40382
|
+
function canonical4(value) {
|
|
40383
|
+
if (value.kind === "string")
|
|
40384
|
+
return JSON.stringify(value.value);
|
|
40385
|
+
if (value.kind === "number" || value.kind === "literal")
|
|
40386
|
+
return value.value;
|
|
40387
|
+
if (value.kind === "array")
|
|
40388
|
+
return "[" + value.items.map(canonical4).join(",") + "]";
|
|
40389
|
+
return "{" + [...value.entries].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, item]) => JSON.stringify(key) + ":" + canonical4(item)).join(",") + "}";
|
|
40390
|
+
}
|
|
40391
|
+
function validateMarketplace(root, selector) {
|
|
40392
|
+
knownKeys(root, MARKETPLACE_KEYS, selector, null);
|
|
40393
|
+
const name = field(root, "name");
|
|
40394
|
+
need4(isString(name) && name.value === selector.marketplace, "marketplace name does not match the reviewed binding");
|
|
40395
|
+
for (const key of ["$schema", "description", "version"]) {
|
|
40396
|
+
const value = field(root, key);
|
|
40397
|
+
need4(value === undefined || isString(value), `has an invalid marketplace ${key}`);
|
|
40398
|
+
}
|
|
40399
|
+
const owner = field(root, "owner");
|
|
40400
|
+
need4(owner === undefined || owner.kind === "object", "has an invalid marketplace owner");
|
|
40401
|
+
const metadata = field(root, "metadata");
|
|
40402
|
+
if (metadata !== undefined) {
|
|
40403
|
+
need4(metadata.kind === "object", "has an invalid marketplace metadata object");
|
|
40404
|
+
knownKeys(metadata, MARKETPLACE_METADATA_KEYS, selector, "metadata");
|
|
40405
|
+
for (const [key, value] of metadata.entries)
|
|
40406
|
+
need4(isString(value), `has an invalid marketplace metadata.${key}`);
|
|
40407
|
+
}
|
|
40408
|
+
const remove = field(root, "forceRemoveDeletedPlugins");
|
|
40409
|
+
need4(remove === undefined || isBoolean(remove), "has an invalid forceRemoveDeletedPlugins value");
|
|
40410
|
+
const cross = field(root, "allowCrossMarketplaceDependenciesOn");
|
|
40411
|
+
need4(cross === undefined || stringArray(cross), "has an invalid allowCrossMarketplaceDependenciesOn value");
|
|
40412
|
+
const renames = field(root, "renames");
|
|
40413
|
+
if (renames !== undefined) {
|
|
40414
|
+
need4(renames.kind === "object" && renames.entries.every(([, target]) => isString(target) || target.kind === "literal" && target.value === "null"), "has an invalid renames map");
|
|
40415
|
+
need4(!renames.entries.some(([from]) => from.toLowerCase() === selector.plugin.toLowerCase()), "plugin id is redirected by the marketplace renames map");
|
|
40416
|
+
}
|
|
40417
|
+
}
|
|
40418
|
+
function validateSource(source, selector, path) {
|
|
40419
|
+
if (isString(source)) {
|
|
40420
|
+
need4(source.value.length > 0, "has an empty plugin source");
|
|
40421
|
+
return;
|
|
40422
|
+
}
|
|
40423
|
+
need4(source?.kind === "object", "has an invalid plugin source");
|
|
40424
|
+
const type = field(source, "source");
|
|
40425
|
+
need4(isString(type) && Object.hasOwn(SOURCE_KEYS, type.value), "has an unreviewed plugin source type");
|
|
40426
|
+
knownKeys(source, new Set(SOURCE_KEYS[type.value]), selector, path);
|
|
40427
|
+
}
|
|
40428
|
+
function projectEntry(entry, selector) {
|
|
40429
|
+
const path = `plugins[${selector.plugin}]`;
|
|
40430
|
+
knownKeys(entry, { has: (key) => ENTRY_BOUND_KEYS.has(key) || ENTRY_OMITTED_KEYS.has(key) }, selector, path);
|
|
40431
|
+
const name = field(entry, "name");
|
|
40432
|
+
need4(isString(name) && name.value === selector.plugin, "selected entry name does not match");
|
|
40433
|
+
validateSource(field(entry, "source"), selector, `${path}.source`);
|
|
40434
|
+
for (const key of ["strict", "defaultEnabled"]) {
|
|
40435
|
+
const value = field(entry, key);
|
|
40436
|
+
need4(value === undefined || isBoolean(value), `has an invalid entry ${key}`);
|
|
40437
|
+
}
|
|
40438
|
+
const headersHelper = field(entry, "headersHelper");
|
|
40439
|
+
need4(headersHelper === undefined || isString(headersHelper), "has an invalid entry headersHelper");
|
|
40440
|
+
const experimental = field(entry, "experimental");
|
|
40441
|
+
if (experimental !== undefined) {
|
|
40442
|
+
need4(experimental.kind === "object", "has an invalid entry experimental object");
|
|
40443
|
+
knownKeys(experimental, EXPERIMENTAL_KEYS, selector, `${path}.experimental`);
|
|
40444
|
+
}
|
|
40445
|
+
for (const key of ["$schema", "description", "version", "homepage", "license", "category", "displayName"]) {
|
|
40446
|
+
const value = field(entry, key);
|
|
40447
|
+
need4(value === undefined || isString(value), `has an invalid entry ${key}`);
|
|
40448
|
+
}
|
|
40449
|
+
for (const [key, keys2] of [["author", new Set(["name", "email", "url"])], ["repository", new Set(["type", "url", "directory"])]]) {
|
|
40450
|
+
const value = field(entry, key);
|
|
40451
|
+
if (value?.kind === "object")
|
|
40452
|
+
knownKeys(value, keys2, selector, `${path}.${key}`);
|
|
40453
|
+
need4(value === undefined || isString(value) || stringObject(value), `has an invalid entry ${key}`);
|
|
40454
|
+
}
|
|
40455
|
+
for (const key of ["keywords", "tags"]) {
|
|
40456
|
+
const value = field(entry, key);
|
|
40457
|
+
need4(value === undefined || stringArray(value), `has an invalid entry ${key}`);
|
|
40458
|
+
}
|
|
40459
|
+
const metadata = field(entry, "metadata");
|
|
40460
|
+
need4(metadata === undefined || metadata.kind === "object", "has an invalid entry metadata object");
|
|
40461
|
+
return { kind: "object", entries: entry.entries.filter(([key]) => ENTRY_BOUND_KEYS.has(key)) };
|
|
40462
|
+
}
|
|
40463
|
+
function hashClaudeMarketplaceEntry(text, selector) {
|
|
40464
|
+
need4(selector && typeof selector.marketplace === "string" && NAME.test(selector.marketplace) && !selector.marketplace.includes("..") && typeof selector.plugin === "string" && NAME.test(selector.plugin), "requires an exact marketplace and plugin name");
|
|
40465
|
+
let root;
|
|
40466
|
+
try {
|
|
40467
|
+
root = parseNativeJsonObject(text);
|
|
40468
|
+
} catch (error) {
|
|
40469
|
+
throw new Error(`Claude marketplace entry witness cannot parse marketplace.json: ${reason(error)}`);
|
|
40470
|
+
}
|
|
40471
|
+
validateMarketplace(root, selector);
|
|
40472
|
+
const plugins = field(root, "plugins");
|
|
40473
|
+
need4(plugins?.kind === "array", "requires a plugins array");
|
|
40474
|
+
const entryName = (item) => {
|
|
40475
|
+
if (item.kind !== "object")
|
|
40476
|
+
return;
|
|
40477
|
+
const name = field(item, "name");
|
|
40478
|
+
return isString(name) ? name.value : undefined;
|
|
40479
|
+
};
|
|
40480
|
+
const exact = plugins.items.filter((item) => entryName(item) === selector.plugin);
|
|
40481
|
+
const folded = plugins.items.filter((item) => entryName(item)?.toLowerCase() === selector.plugin.toLowerCase());
|
|
40482
|
+
need4(exact.length > 0, "selected plugin entry is missing");
|
|
40483
|
+
need4(exact.length === 1 && folded.length === 1, "selected plugin entry is duplicated or ambiguous");
|
|
40484
|
+
const entry = projectEntry(exact[0], selector);
|
|
40485
|
+
const metadata = field(root, "metadata"), pluginRoot = metadata?.kind === "object" ? field(metadata, "pluginRoot") : undefined;
|
|
40486
|
+
const nullValue = { kind: "literal", value: "null" };
|
|
40487
|
+
const marketplace = { kind: "object", entries: [
|
|
40488
|
+
["name", field(root, "name")],
|
|
40489
|
+
["pluginRoot", pluginRoot ?? nullValue],
|
|
40490
|
+
["allowCrossMarketplaceDependenciesOn", field(root, "allowCrossMarketplaceDependenciesOn") ?? nullValue]
|
|
40491
|
+
] };
|
|
40492
|
+
const projection = { kind: "object", entries: [["marketplace", marketplace], ["plugin", entry]] };
|
|
40493
|
+
return createHash12("sha256").update(DOMAIN).update(canonical4(projection)).digest("hex");
|
|
40494
|
+
}
|
|
40495
|
+
function captureClaudeMarketplaceEntry(path, marketplace, plugin, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
40496
|
+
need4(claudeMarketplaceEntrySourceValid({ path, marketplace, plugin }), "requires a normalized absolute .claude-plugin/marketplace.json path and exact names");
|
|
40497
|
+
let text;
|
|
40498
|
+
try {
|
|
40499
|
+
text = readNativeSettingsWitnessFile(path, budget2, "marketplace.json");
|
|
40500
|
+
} catch (error) {
|
|
40501
|
+
throw new Error(`Claude marketplace entry witness cannot read marketplace.json: ${reason(error)}`);
|
|
40502
|
+
}
|
|
40503
|
+
return { path, hashMode: CLAUDE_MARKETPLACE_ENTRY_HASH_MODE, marketplace, plugin, sha256: hashClaudeMarketplaceEntry(text, { marketplace, plugin }) };
|
|
40504
|
+
}
|
|
40505
|
+
|
|
40506
|
+
// src/lib/agent-policy-limits.ts
|
|
40291
40507
|
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 });
|
|
40292
40508
|
function object4(value) {
|
|
40293
40509
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
@@ -40341,7 +40557,7 @@ function assertAgentPolicyCollections(policy) {
|
|
|
40341
40557
|
text(control.pluginId, 1024);
|
|
40342
40558
|
text(control.namespace, 64);
|
|
40343
40559
|
text(control.pluginParent);
|
|
40344
|
-
requireBound(
|
|
40560
|
+
requireBound(isAbsolute9(control.pluginParent) && resolve8(control.pluginParent) === control.pluginParent && /^[a-f0-9]{64}$/.test(control.manifestSha256));
|
|
40345
40561
|
if (control.remotePluginId !== undefined)
|
|
40346
40562
|
requireBound(typeof control.remotePluginId === "string" && /^[A-Za-z0-9_~-]{1,1024}$/.test(control.remotePluginId));
|
|
40347
40563
|
if (control.skillsOnly !== undefined)
|
|
@@ -40353,16 +40569,24 @@ function assertAgentPolicyCollections(policy) {
|
|
|
40353
40569
|
}
|
|
40354
40570
|
if (bridge.codexInactivePlugins !== undefined) {
|
|
40355
40571
|
const controls = array(bridge.codexInactivePlugins, 4096), ids = new Set;
|
|
40356
|
-
requireBound(controls.length === 0 || object4(bridge.codexPluginSkillReview) && bridge.codexPluginSkillReview.version
|
|
40572
|
+
requireBound(controls.length === 0 || object4(bridge.codexPluginSkillReview) && supportsCodexNativeCapability(bridge.codexPluginSkillReview.version, "installed-plugin-review") && typeof bridge.codexPluginSkillReview.catalogSha256 === "string" && /^[a-f0-9]{64}$/.test(bridge.codexPluginSkillReview.catalogSha256));
|
|
40357
40573
|
for (const control of controls) {
|
|
40358
40574
|
requireBound(object4(control) && Object.keys(control).every((key) => ["pluginId", "namespace", "pluginParent", "sourceType", "sourceSha256"].includes(key)));
|
|
40359
40575
|
text(control.pluginId, 1024);
|
|
40360
40576
|
text(control.namespace, 64);
|
|
40361
40577
|
text(control.pluginParent);
|
|
40362
|
-
requireBound(!ids.has(control.pluginId) &&
|
|
40578
|
+
requireBound(!ids.has(control.pluginId) && isAbsolute9(control.pluginParent) && resolve8(control.pluginParent) === control.pluginParent && ["local", "git", "npm"].includes(control.sourceType) && typeof control.sourceSha256 === "string" && /^[a-f0-9]{64}$/.test(control.sourceSha256));
|
|
40363
40579
|
ids.add(control.pluginId);
|
|
40364
40580
|
}
|
|
40365
40581
|
}
|
|
40582
|
+
if (bridge.discoveryExecutables !== undefined)
|
|
40583
|
+
for (const [agent, executable2] of Object.entries(record3(bridge.discoveryExecutables, AGENT_POLICY_LIMITS.agents))) {
|
|
40584
|
+
requireBound(agent === "gemini" && object4(executable2) && Object.keys(executable2).length === 3 && executable2.command === "gemini");
|
|
40585
|
+
for (const path of [executable2.path, executable2.target]) {
|
|
40586
|
+
text(path);
|
|
40587
|
+
requireBound(!/[\x00-\x1f\x7f-\x9f\u200e\u200f\u202a-\u202e\u2066-\u2069]/.test(path) && isAbsolute9(path) && resolve8(path) === path);
|
|
40588
|
+
}
|
|
40589
|
+
}
|
|
40366
40590
|
if (bridge.disabledBuiltins !== undefined)
|
|
40367
40591
|
for (const builtin of array(bridge.disabledBuiltins, AGENT_POLICY_LIMITS.builtinNames)) {
|
|
40368
40592
|
requireBound(object4(builtin));
|
|
@@ -40388,11 +40612,11 @@ function assertAgentPolicyCollections(policy) {
|
|
|
40388
40612
|
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && Object.keys(proof).every((key) => ["roots", "parents", "directories"].includes(key)) && roots.length + parents2.length > 0 && new Set(roots).size === roots.length && new Set(parents2).size === parents2.length);
|
|
40389
40613
|
for (const root of roots) {
|
|
40390
40614
|
text(root);
|
|
40391
|
-
requireBound(
|
|
40615
|
+
requireBound(isAbsolute9(root) && resolve8(root) === root);
|
|
40392
40616
|
}
|
|
40393
40617
|
for (const parent of parents2) {
|
|
40394
40618
|
text(parent);
|
|
40395
|
-
requireBound(
|
|
40619
|
+
requireBound(isAbsolute9(parent) && resolve8(parent) === parent);
|
|
40396
40620
|
}
|
|
40397
40621
|
for (const directory of array(proof.directories, AGENT_POLICY_LIMITS.discoveryDirectories)) {
|
|
40398
40622
|
requireBound(object4(directory));
|
|
@@ -40405,14 +40629,14 @@ function assertAgentPolicyCollections(policy) {
|
|
|
40405
40629
|
}
|
|
40406
40630
|
if (value.codexInstallationInputs !== undefined) {
|
|
40407
40631
|
const proof = record3(value.codexInstallationInputs, 4), inputs = array(proof.plugins, 4096), ids = new Set;
|
|
40408
|
-
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && proof.version
|
|
40632
|
+
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && supportsCodexNativeCapability(proof.version, "installed-plugin-review") && typeof proof.catalogSha256 === "string" && /^[a-f0-9]{64}$/.test(proof.catalogSha256) && inputs.length > 0 && object4(bridge.codexPluginSkillReview) && bridge.codexPluginSkillReview.version === proof.version && bridge.codexPluginSkillReview.catalogSha256 === proof.catalogSha256);
|
|
40409
40633
|
for (const input of inputs) {
|
|
40410
40634
|
requireBound(object4(input) && Object.keys(input).every((key) => ["pluginId", "namespace", "pluginParent", "sourceRoot", "sourceSha256"].includes(key)));
|
|
40411
40635
|
text(input.pluginId, 1024);
|
|
40412
40636
|
text(input.namespace, 64);
|
|
40413
40637
|
text(input.pluginParent);
|
|
40414
40638
|
text(input.sourceRoot);
|
|
40415
|
-
requireBound(!ids.has(input.pluginId) && [input.pluginParent, input.sourceRoot].every((path) =>
|
|
40639
|
+
requireBound(!ids.has(input.pluginId) && [input.pluginParent, input.sourceRoot].every((path) => isAbsolute9(path) && resolve8(path) === path) && typeof input.sourceSha256 === "string" && /^[a-f0-9]{64}$/.test(input.sourceSha256));
|
|
40416
40640
|
ids.add(input.pluginId);
|
|
40417
40641
|
}
|
|
40418
40642
|
if (proof.directories !== undefined)
|
|
@@ -40429,17 +40653,19 @@ function assertAgentPolicyCollections(policy) {
|
|
|
40429
40653
|
text(source.path);
|
|
40430
40654
|
requireBound(source.sha256 === null || typeof source.sha256 === "string" && /^[a-f0-9]{64}$/.test(source.sha256));
|
|
40431
40655
|
if (source.hashMode !== undefined)
|
|
40432
|
-
requireBound(["bytes", "path-bytes", "claude-plugin-manifest-v1", "claude-plugin-registry", "claude-marketplace-registry", "claude-settings-v1", "claude-settings-v2", "claude-settings-v3", "claude-settings-v4", "claude-marketplace-registry-v2", "codex-settings-v1", "codex-settings-v2", "codex-settings-v3", "codex-settings-v4", "sumi-settings-v1"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
|
|
40656
|
+
requireBound(["bytes", "path-bytes", "claude-plugin-manifest-v1", "claude-plugin-registry", "claude-marketplace-registry", "claude-settings-v1", "claude-settings-v2", "claude-settings-v3", "claude-settings-v4", "claude-marketplace-registry-v2", "codex-settings-v1", "codex-settings-v2", "codex-settings-v3", "codex-settings-v4", "sumi-settings-v1", "claude-marketplace-entry-v1"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
|
|
40433
40657
|
if (source.hashMode === "claude-plugin-manifest-v1")
|
|
40434
|
-
requireBound(agent === "claude" && value.agent === "claude" && ["automatic", "reviewed"].includes(value.method) && !/[\x00-\x1f\x7f]/.test(source.path) &&
|
|
40658
|
+
requireBound(agent === "claude" && value.agent === "claude" && ["automatic", "reviewed"].includes(value.method) && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute9(source.path) && resolve8(source.path) === source.path && source.path.endsWith(join14(sep4, ".claude-plugin", "plugin.json")) && source.managedPlugins === undefined);
|
|
40435
40659
|
if (source.hashMode === "sumi-settings-v1")
|
|
40436
|
-
requireBound(agent === "sumi" && value.agent === "sumi" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) &&
|
|
40660
|
+
requireBound(agent === "sumi" && value.agent === "sumi" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute9(source.path) && resolve8(source.path) === source.path && basename6(source.path) === "sumi.json");
|
|
40437
40661
|
if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4"))
|
|
40438
|
-
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) &&
|
|
40662
|
+
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute9(source.path) && resolve8(source.path) === source.path && basename6(source.path) === "config.toml");
|
|
40439
40663
|
if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4"))
|
|
40440
|
-
requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) &&
|
|
40664
|
+
requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute9(source.path) && resolve8(source.path) === source.path && basename6(source.path) === "settings.json");
|
|
40441
40665
|
if (source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2")
|
|
40442
|
-
requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) &&
|
|
40666
|
+
requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute9(source.path) && resolve8(source.path) === source.path && basename6(source.path) === "known_marketplaces.json");
|
|
40667
|
+
if (source.hashMode === "claude-marketplace-entry-v1")
|
|
40668
|
+
requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && claudeMarketplaceEntrySourceValid(source));
|
|
40443
40669
|
if (source.hashMode === "claude-plugin-registry") {
|
|
40444
40670
|
requireBound(agent === "claude");
|
|
40445
40671
|
const managed = array(source.managedPlugins, 64);
|
|
@@ -40454,8 +40680,8 @@ function assertAgentPolicyCollections(policy) {
|
|
|
40454
40680
|
if (source.format !== undefined)
|
|
40455
40681
|
requireBound(["json", "toml", "yaml"].includes(source.format));
|
|
40456
40682
|
if (source.fields !== undefined)
|
|
40457
|
-
for (const
|
|
40458
|
-
text(
|
|
40683
|
+
for (const field2 of array(source.fields, AGENT_POLICY_LIMITS.fields))
|
|
40684
|
+
text(field2, 256);
|
|
40459
40685
|
}
|
|
40460
40686
|
if (value.directories !== undefined)
|
|
40461
40687
|
for (const directory of array(value.directories, AGENT_POLICY_LIMITS.discoveryDirectories)) {
|
|
@@ -40470,8 +40696,8 @@ function assertAgentPolicyCollections(policy) {
|
|
|
40470
40696
|
}
|
|
40471
40697
|
|
|
40472
40698
|
// src/lib/managed-policy.ts
|
|
40473
|
-
function refusal(
|
|
40474
|
-
return new SkillSelectionError("INVALID_AGENT_POLICY", `The Skills agent loading policy ${
|
|
40699
|
+
function refusal(reason2 = "is unreadable") {
|
|
40700
|
+
return new SkillSelectionError("INVALID_AGENT_POLICY", `The Skills agent loading policy ${reason2}; refusing legacy fallback.`);
|
|
40475
40701
|
}
|
|
40476
40702
|
function parseManagedSkillPolicy(text2) {
|
|
40477
40703
|
if (Buffer.byteLength(text2) > AGENT_POLICY_LIMITS.bytes)
|
|
@@ -40548,7 +40774,7 @@ function requiresCliSkillLoading(dataDir2 = getDataDirReadOnly()) {
|
|
|
40548
40774
|
}
|
|
40549
40775
|
|
|
40550
40776
|
// src/lib/agent-bridge.ts
|
|
40551
|
-
import { createHash as
|
|
40777
|
+
import { createHash as createHash13 } from "crypto";
|
|
40552
40778
|
import { lstatSync as lstatSync10, readFileSync as readFileSync11, readdirSync as readdirSync4 } from "fs";
|
|
40553
40779
|
import { join as join16 } from "path";
|
|
40554
40780
|
var CLI_BRIDGE_NAME = "skills-cli";
|
|
@@ -40567,7 +40793,7 @@ Use the Skills CLI as the skill authority for this station.
|
|
|
40567
40793
|
|
|
40568
40794
|
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.
|
|
40569
40795
|
`;
|
|
40570
|
-
var CLI_BRIDGE_DIGEST =
|
|
40796
|
+
var CLI_BRIDGE_DIGEST = createHash13("sha256").update(markdown).digest("hex");
|
|
40571
40797
|
var CLI_BRIDGE_FILES = Object.freeze({
|
|
40572
40798
|
"SKILL.md": markdown,
|
|
40573
40799
|
".hasna-skills.json": `${JSON.stringify({ managedBy: "@hasna/skills", kind: "cli-bridge", version: CLI_BRIDGE_VERSION, protocol: "selection-v1", contentSha256: CLI_BRIDGE_DIGEST }, null, 2)}
|
|
@@ -40591,9 +40817,9 @@ function isOwnedCliBridge(path, expectedPaths) {
|
|
|
40591
40817
|
}
|
|
40592
40818
|
|
|
40593
40819
|
// src/lib/agent-discovery.ts
|
|
40594
|
-
import { createHash as
|
|
40820
|
+
import { createHash as createHash23 } from "crypto";
|
|
40595
40821
|
import { lstatSync as lstatSync21, readFileSync as readFileSync15, readdirSync as readdirSync7, realpathSync as realpathSync9 } from "fs";
|
|
40596
|
-
import { basename as
|
|
40822
|
+
import { basename as basename9, dirname as dirname17, isAbsolute as isAbsolute20, join as join26, resolve as resolve19, sep as sep6 } from "path";
|
|
40597
40823
|
import { isDeepStrictEqual as isDeepStrictEqual6 } from "util";
|
|
40598
40824
|
|
|
40599
40825
|
// node_modules/yaml/dist/index.js
|
|
@@ -40643,7 +40869,7 @@ var $visit = visit.visit;
|
|
|
40643
40869
|
var $visitAsync = visit.visitAsync;
|
|
40644
40870
|
|
|
40645
40871
|
// src/lib/agent-hermes.ts
|
|
40646
|
-
import { dirname as
|
|
40872
|
+
import { dirname as dirname9, isAbsolute as isAbsolute10, join as join17, resolve as resolve9 } from "path";
|
|
40647
40873
|
import { lstatSync as lstatSync11, readFileSync as readFileSync12, opendirSync } from "fs";
|
|
40648
40874
|
var HERMES_OPT_OUT = ".no-bundled-skills";
|
|
40649
40875
|
var EVENTS = ["pre_llm_call", "pre_tool_call"];
|
|
@@ -40681,7 +40907,7 @@ function quoted(value) {
|
|
|
40681
40907
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
40682
40908
|
}
|
|
40683
40909
|
function hermesHookDefinitions(supervisor) {
|
|
40684
|
-
if (!
|
|
40910
|
+
if (!isAbsolute10(supervisor.runtime) || !isAbsolute10(supervisor.path))
|
|
40685
40911
|
throw new Error("Expected absolute Hermes supervisor paths");
|
|
40686
40912
|
const entry = (event) => ({ command: `${quoted(supervisor.runtime)} ${quoted(supervisor.path)} --event ${event}`, timeout: 15, ...event === "pre_tool_call" ? { fail_closed: true } : {} });
|
|
40687
40913
|
return { pre_llm_call: entry("pre_llm_call"), pre_tool_call: entry("pre_tool_call") };
|
|
@@ -40717,16 +40943,16 @@ function assertHermesEnvironment(home) {
|
|
|
40717
40943
|
throw new Error(`NATIVE_SKILL_DRIFT: Hermes ${variable} requires a dedicated discovery adapter; unset it before using this adapter`);
|
|
40718
40944
|
}
|
|
40719
40945
|
const selected = process.env.HERMES_HOME?.trim();
|
|
40720
|
-
if (selected && (!
|
|
40946
|
+
if (selected && (!isAbsolute10(selected) || resolve9(selected) !== join17(resolve9(home), ".hermes")))
|
|
40721
40947
|
throw new Error("NATIVE_SKILL_DRIFT: custom Hermes homes/profiles require their own reviewed bridge");
|
|
40722
40948
|
if (process.env.HERMES_ENABLE_PROJECT_PLUGINS?.trim() && !["0", "false", "no", "off"].includes(process.env.HERMES_ENABLE_PROJECT_PLUGINS.trim().toLowerCase()))
|
|
40723
40949
|
throw new Error("NATIVE_SKILL_DRIFT: Hermes project plugins require a dedicated discovery review");
|
|
40724
40950
|
}
|
|
40725
40951
|
function read(path) {
|
|
40726
|
-
for (let current = path;; current =
|
|
40952
|
+
for (let current = path;; current = dirname9(current)) {
|
|
40727
40953
|
if (lstatSync11(current, { throwIfNoEntry: false })?.isSymbolicLink())
|
|
40728
40954
|
throw new Error("NATIVE_SKILL_DRIFT: symlink Hermes protection input");
|
|
40729
|
-
if (
|
|
40955
|
+
if (dirname9(current) === current)
|
|
40730
40956
|
break;
|
|
40731
40957
|
}
|
|
40732
40958
|
const stat = lstatSync11(path, { throwIfNoEntry: false });
|
|
@@ -40740,7 +40966,7 @@ function assertHermesProtection(home, config, command, profile, supervisor) {
|
|
|
40740
40966
|
assertHermesEnvironment(home);
|
|
40741
40967
|
if (read(join17(home, ".hermes", HERMES_OPT_OUT)) === null)
|
|
40742
40968
|
throw new Error("NATIVE_SKILL_DRIFT: Hermes bundled skill reseeding is not disabled; run skills hook install");
|
|
40743
|
-
if (!supervisor || !
|
|
40969
|
+
if (!supervisor || !isAbsolute10(supervisor.path) || supervisor.runtime !== process.execPath || read(supervisor.path) !== renderHermesSupervisor(command, profile))
|
|
40744
40970
|
throw new Error("NATIVE_SKILL_DRIFT: Hermes owned supervisor changed; run skills hook install");
|
|
40745
40971
|
const raw = read(join17(home, ".hermes/shell-hooks-allowlist.json"));
|
|
40746
40972
|
let trust;
|
|
@@ -40766,10 +40992,10 @@ function assertHermesProtection(home, config, command, profile, supervisor) {
|
|
|
40766
40992
|
}
|
|
40767
40993
|
function assertNoHermesLegacyShadow(root) {
|
|
40768
40994
|
let entries = 0;
|
|
40769
|
-
for (let cursor =
|
|
40995
|
+
for (let cursor = resolve9(root);; cursor = dirname9(cursor)) {
|
|
40770
40996
|
if (lstatSync11(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
|
|
40771
40997
|
throw new Error("NATIVE_SKILL_DRIFT: symlink Hermes legacy discovery root");
|
|
40772
|
-
if (
|
|
40998
|
+
if (dirname9(cursor) === cursor)
|
|
40773
40999
|
break;
|
|
40774
41000
|
}
|
|
40775
41001
|
function scan(path, depth) {
|
|
@@ -40790,10 +41016,10 @@ function assertNoHermesLegacyShadow(root) {
|
|
|
40790
41016
|
const hasDescriptor = Boolean(lstatSync11(join17(path, "SKILL.md"), { throwIfNoEntry: false }));
|
|
40791
41017
|
const directory = opendirSync(path);
|
|
40792
41018
|
try {
|
|
40793
|
-
for (let
|
|
40794
|
-
if (hasDescriptor && ["references", "templates", "assets", "scripts"].includes(
|
|
41019
|
+
for (let child2 = directory.readSync();child2; child2 = directory.readSync()) {
|
|
41020
|
+
if (hasDescriptor && ["references", "templates", "assets", "scripts"].includes(child2.name))
|
|
40795
41021
|
continue;
|
|
40796
|
-
scan(join17(path,
|
|
41022
|
+
scan(join17(path, child2.name), depth + 1);
|
|
40797
41023
|
}
|
|
40798
41024
|
} finally {
|
|
40799
41025
|
directory.closeSync();
|
|
@@ -40850,18 +41076,18 @@ if (failed) process.exitCode = 2;
|
|
|
40850
41076
|
}
|
|
40851
41077
|
|
|
40852
41078
|
// src/lib/agent-discovery-directories.ts
|
|
40853
|
-
import { createHash as
|
|
41079
|
+
import { createHash as createHash14 } from "crypto";
|
|
40854
41080
|
import { lstatSync as lstatSync12, opendirSync as opendirSync2 } from "fs";
|
|
40855
|
-
import { dirname as
|
|
40856
|
-
function
|
|
41081
|
+
import { dirname as dirname10, isAbsolute as isAbsolute11, join as join18, resolve as resolve10 } from "path";
|
|
41082
|
+
function need5(value, message) {
|
|
40857
41083
|
if (!value)
|
|
40858
41084
|
throw new Error(message);
|
|
40859
41085
|
}
|
|
40860
41086
|
function safe(path) {
|
|
40861
|
-
|
|
40862
|
-
for (let cursor = path;; cursor =
|
|
40863
|
-
|
|
40864
|
-
if (
|
|
41087
|
+
need5(typeof path === "string" && path.length <= AGENT_POLICY_LIMITS.pathCharacters && isAbsolute11(path) && resolve10(path) === path && !path.includes("\x00"), "Expected a canonical absolute discovery directory path");
|
|
41088
|
+
for (let cursor = path;; cursor = dirname10(cursor)) {
|
|
41089
|
+
need5(!lstatSync12(cursor, { throwIfNoEntry: false })?.isSymbolicLink(), "Refusing symlink native discovery directory");
|
|
41090
|
+
if (dirname10(cursor) === cursor)
|
|
40865
41091
|
break;
|
|
40866
41092
|
}
|
|
40867
41093
|
}
|
|
@@ -40875,45 +41101,45 @@ function capture(path, budget2, excludedRoots, omittedRoots = [], rows) {
|
|
|
40875
41101
|
const root = lstatSync12(path, { throwIfNoEntry: false });
|
|
40876
41102
|
if (!root)
|
|
40877
41103
|
return { path, sha256: null };
|
|
40878
|
-
|
|
40879
|
-
const hash2 =
|
|
41104
|
+
need5(root.isDirectory(), "Unsupported native discovery directory input");
|
|
41105
|
+
const hash2 = createHash14("sha256");
|
|
40880
41106
|
function walk2(current, relative5, before, depth) {
|
|
40881
|
-
|
|
41107
|
+
need5(depth <= 64, "Native discovery directory depth limit exceeded");
|
|
40882
41108
|
const names = [], directory = opendirSync2(current);
|
|
40883
41109
|
try {
|
|
40884
41110
|
for (let entry = directory.readSync();entry; entry = directory.readSync()) {
|
|
40885
|
-
|
|
41111
|
+
need5(++budget2.entries <= AGENT_POLICY_LIMITS.discoveryDirectoryEntries, "Native discovery directory entry limit exceeded");
|
|
40886
41112
|
names.push(entry.name);
|
|
40887
41113
|
}
|
|
40888
41114
|
} finally {
|
|
40889
41115
|
directory.closeSync();
|
|
40890
41116
|
}
|
|
40891
|
-
|
|
41117
|
+
need5(new Set(names).size === names.length, "Ambiguous native discovery directory names");
|
|
40892
41118
|
for (const name of names.sort()) {
|
|
40893
|
-
const
|
|
40894
|
-
if (omittedRoots.includes(
|
|
41119
|
+
const child2 = join18(current, name), childRelative = relative5 ? `${relative5}/${name}` : name;
|
|
41120
|
+
if (omittedRoots.includes(child2))
|
|
40895
41121
|
continue;
|
|
40896
|
-
|
|
40897
|
-
const stat = lstatSync12(
|
|
40898
|
-
|
|
41122
|
+
need5(child2.length <= AGENT_POLICY_LIMITS.pathCharacters, "Native discovery directory path limit exceeded");
|
|
41123
|
+
const stat = lstatSync12(child2);
|
|
41124
|
+
need5(stat.isFile() || stat.isDirectory(), "Refusing symlink or special native discovery directory member");
|
|
40899
41125
|
const row = JSON.stringify([childRelative, stat.isDirectory() ? "directory" : "file"]) + `
|
|
40900
41126
|
`;
|
|
40901
41127
|
budget2.bytes += Buffer.byteLength(row);
|
|
40902
|
-
|
|
41128
|
+
need5(budget2.bytes <= AGENT_POLICY_LIMITS.discoveryDirectoryBytes, "Native discovery directory metadata limit exceeded");
|
|
40903
41129
|
hash2.update(row);
|
|
40904
41130
|
rows?.push(row);
|
|
40905
|
-
if (stat.isDirectory() && !excludedRoots.includes(
|
|
40906
|
-
walk2(
|
|
41131
|
+
if (stat.isDirectory() && !excludedRoots.includes(child2))
|
|
41132
|
+
walk2(child2, childRelative, stat, depth + 1);
|
|
40907
41133
|
}
|
|
40908
|
-
|
|
41134
|
+
need5(same(before, lstatSync12(current, { throwIfNoEntry: false })), "Native discovery directory changed while reading");
|
|
40909
41135
|
}
|
|
40910
41136
|
walk2(path, "", root, 0);
|
|
40911
41137
|
safe(path);
|
|
40912
41138
|
return { path, sha256: hash2.digest("hex") };
|
|
40913
41139
|
}
|
|
40914
41140
|
function captureDiscoveryDirectoryProjection(paths, omittedRoots) {
|
|
40915
|
-
|
|
40916
|
-
|
|
41141
|
+
need5(Array.isArray(paths) && paths.length <= AGENT_POLICY_LIMITS.discoveryDirectories && new Set(paths).size === paths.length, "Invalid projected discovery directory collection");
|
|
41142
|
+
need5(omittedRoots.length <= AGENT_POLICY_LIMITS.discoveryRoots && new Set(omittedRoots).size === omittedRoots.length, "Invalid inactive discovery roots");
|
|
40917
41143
|
for (const root of omittedRoots)
|
|
40918
41144
|
safe(root);
|
|
40919
41145
|
const budget2 = { entries: 0, bytes: 0 };
|
|
@@ -40923,62 +41149,62 @@ function captureDiscoveryDirectoryProjection(paths, omittedRoots) {
|
|
|
40923
41149
|
});
|
|
40924
41150
|
}
|
|
40925
41151
|
function verifyDiscoveryDirectoryProjection(directories, omittedRoots) {
|
|
40926
|
-
|
|
41152
|
+
need5(directories.length <= AGENT_POLICY_LIMITS.discoveryDirectories, "Invalid projected discovery directory collection");
|
|
40927
41153
|
let count = 0, bytes = 0;
|
|
40928
41154
|
const expected = directories.map((directory) => {
|
|
40929
41155
|
safe(directory.path);
|
|
40930
|
-
|
|
40931
|
-
const hash2 =
|
|
41156
|
+
need5(Array.isArray(directory.entries), "Missing reviewed directory membership inventory");
|
|
41157
|
+
const hash2 = createHash14("sha256");
|
|
40932
41158
|
const kept = [];
|
|
40933
41159
|
for (const row of directory.entries) {
|
|
40934
|
-
|
|
41160
|
+
need5(typeof row === "string" && ++count <= AGENT_POLICY_LIMITS.discoveryDirectoryEntries, "Invalid reviewed directory membership rows");
|
|
40935
41161
|
bytes += Buffer.byteLength(row);
|
|
40936
|
-
|
|
41162
|
+
need5(bytes <= AGENT_POLICY_LIMITS.discoveryDirectoryBytes, "Reviewed directory membership byte limit exceeded");
|
|
40937
41163
|
const value = JSON.parse(row);
|
|
40938
|
-
|
|
41164
|
+
need5(Array.isArray(value) && value.length === 2 && typeof value[0] === "string" && value[0] && !isAbsolute11(value[0]) && !value[0].split("/").some((part) => !part || part === "." || part === "..") && ["file", "directory"].includes(value[1]) && row === JSON.stringify(value) + `
|
|
40939
41165
|
`, "Invalid reviewed directory member");
|
|
40940
41166
|
hash2.update(row);
|
|
40941
41167
|
const path = join18(directory.path, value[0]);
|
|
40942
41168
|
if (!omittedRoots.some((root) => path === root || path.startsWith(root + "/")))
|
|
40943
41169
|
kept.push(row);
|
|
40944
41170
|
}
|
|
40945
|
-
|
|
41171
|
+
need5(directory.sha256 === null ? directory.entries.length === 0 : hash2.digest("hex") === directory.sha256, "Reviewed directory inventory does not match its fingerprint");
|
|
40946
41172
|
const absent = omittedRoots.some((root) => directory.path === root || directory.path.startsWith(root + "/"));
|
|
40947
|
-
return { path: directory.path, sha256: absent || directory.sha256 === null ? null :
|
|
41173
|
+
return { path: directory.path, sha256: absent || directory.sha256 === null ? null : createHash14("sha256").update(kept.join("")).digest("hex") };
|
|
40948
41174
|
});
|
|
40949
41175
|
const current = captureDiscoveryDirectoryProjection(directories.map((item) => item.path), omittedRoots);
|
|
40950
|
-
|
|
41176
|
+
need5(current.every((item, index) => item.sha256 === expected[index].sha256), "Native discovery directory membership changed outside retired Codex roots");
|
|
40951
41177
|
}
|
|
40952
41178
|
function captureDiscoveryDirectories(paths, excludedRoots = []) {
|
|
40953
|
-
|
|
41179
|
+
need5(Array.isArray(paths) && paths.length <= AGENT_POLICY_LIMITS.discoveryDirectories && new Set(paths).size === paths.length, "Invalid native discovery directory collection");
|
|
40954
41180
|
const budget2 = { entries: 0, bytes: 0 };
|
|
40955
41181
|
for (const root of excludedRoots)
|
|
40956
41182
|
safe(root);
|
|
40957
41183
|
return paths.map((path) => capture(path, budget2, excludedRoots));
|
|
40958
41184
|
}
|
|
40959
41185
|
function verifyDiscoveryDirectories(directories, excludedRoots = []) {
|
|
40960
|
-
|
|
41186
|
+
need5(Array.isArray(directories) && directories.length <= AGENT_POLICY_LIMITS.discoveryDirectories, "Invalid native discovery directory collection");
|
|
40961
41187
|
for (const directory of directories)
|
|
40962
|
-
|
|
41188
|
+
need5(directory && typeof directory === "object" && (directory.sha256 === null || typeof directory.sha256 === "string" && /^[a-f0-9]{64}$/.test(directory.sha256)), "Invalid native discovery directory digest");
|
|
40963
41189
|
const current = captureDiscoveryDirectories(directories.map((directory) => directory.path), excludedRoots);
|
|
40964
41190
|
for (let i = 0;i < directories.length; i++)
|
|
40965
|
-
|
|
41191
|
+
need5(current[i].sha256 === directories[i].sha256, `Native discovery directory membership changed; run skills hook install with a fresh discovery review: ${directories[i].path}`);
|
|
40966
41192
|
}
|
|
40967
41193
|
|
|
40968
41194
|
// src/lib/agent-discovery-bytes.ts
|
|
40969
|
-
import { createHash as
|
|
41195
|
+
import { createHash as createHash15 } from "crypto";
|
|
40970
41196
|
import { closeSync as closeSync12, constants as constants9, fstatSync as fstatSync12, lstatSync as lstatSync13, openSync as openSync12, readSync as readSync7 } from "fs";
|
|
40971
|
-
import { dirname as
|
|
41197
|
+
import { dirname as dirname11, isAbsolute as isAbsolute12, resolve as resolve11 } from "path";
|
|
40972
41198
|
function discoveryByteBudget() {
|
|
40973
41199
|
return { remaining: AGENT_POLICY_LIMITS.discoveryRawTotalBytes };
|
|
40974
41200
|
}
|
|
40975
41201
|
function safe2(path) {
|
|
40976
|
-
if (typeof path !== "string" || !
|
|
41202
|
+
if (typeof path !== "string" || !isAbsolute12(path) || path !== resolve11(path) || path.length > AGENT_POLICY_LIMITS.pathCharacters || path.includes("\x00"))
|
|
40977
41203
|
throw new Error("Expected a canonical absolute raw discovery path");
|
|
40978
|
-
for (let cursor = path;; cursor =
|
|
41204
|
+
for (let cursor = path;; cursor = dirname11(cursor)) {
|
|
40979
41205
|
if (lstatSync13(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
|
|
40980
41206
|
throw new Error("Refusing symlink raw discovery input");
|
|
40981
|
-
if (
|
|
41207
|
+
if (dirname11(cursor) === cursor)
|
|
40982
41208
|
break;
|
|
40983
41209
|
}
|
|
40984
41210
|
}
|
|
@@ -40997,7 +41223,7 @@ function hashRawDiscoveryFile(path, budget2, changes) {
|
|
|
40997
41223
|
if (bytes > AGENT_POLICY_LIMITS.discoveryRawSourceBytes)
|
|
40998
41224
|
throw new Error("Raw discovery file byte limit exceeded");
|
|
40999
41225
|
consume(budget2, bytes);
|
|
41000
|
-
return
|
|
41226
|
+
return createHash15("sha256").update(text2).digest("hex");
|
|
41001
41227
|
}
|
|
41002
41228
|
const initial = lstatSync13(path, { throwIfNoEntry: false });
|
|
41003
41229
|
if (!initial)
|
|
@@ -41011,7 +41237,7 @@ function hashRawDiscoveryFile(path, budget2, changes) {
|
|
|
41011
41237
|
const opened = fstatSync12(fd);
|
|
41012
41238
|
if (!opened.isFile() || !same2(initial, opened))
|
|
41013
41239
|
throw new Error("Raw discovery input changed during open");
|
|
41014
|
-
const hash2 =
|
|
41240
|
+
const hash2 = createHash15("sha256"), buffer = Buffer.alloc(64 * 1024);
|
|
41015
41241
|
let bytes = 0;
|
|
41016
41242
|
while (true) {
|
|
41017
41243
|
const count = readSync7(fd, buffer, 0, Math.min(buffer.length, AGENT_POLICY_LIMITS.discoveryRawSourceBytes - bytes + 1), null);
|
|
@@ -41034,9 +41260,9 @@ function hashRawDiscoveryFile(path, budget2, changes) {
|
|
|
41034
41260
|
}
|
|
41035
41261
|
|
|
41036
41262
|
// src/lib/agent-discovery-path-bytes.ts
|
|
41037
|
-
import { createHash as
|
|
41263
|
+
import { createHash as createHash16 } from "crypto";
|
|
41038
41264
|
import { lstatSync as lstatSync14, readlinkSync as readlinkSync4 } from "fs";
|
|
41039
|
-
import { dirname as
|
|
41265
|
+
import { dirname as dirname12, isAbsolute as isAbsolute13, join as join19, parse as parse3, resolve as resolve12, sep as sep5 } from "path";
|
|
41040
41266
|
function identity4(stat, mutable = false) {
|
|
41041
41267
|
return {
|
|
41042
41268
|
dev: String(stat.dev),
|
|
@@ -41047,12 +41273,12 @@ function identity4(stat, mutable = false) {
|
|
|
41047
41273
|
...mutable ? { size: String(stat.size), mtimeNs: String(stat.mtimeNs), ctimeNs: String(stat.ctimeNs) } : {}
|
|
41048
41274
|
};
|
|
41049
41275
|
}
|
|
41050
|
-
function
|
|
41051
|
-
if (typeof path !== "string" || !
|
|
41276
|
+
function canonical5(path) {
|
|
41277
|
+
if (typeof path !== "string" || !isAbsolute13(path) || path !== resolve12(path) || path.length > AGENT_POLICY_LIMITS.pathCharacters || path.includes("\x00") || Buffer.from(path).toString("utf8") !== path)
|
|
41052
41278
|
throw new Error("Expected a canonical absolute discovery path");
|
|
41053
41279
|
}
|
|
41054
41280
|
function trace(path) {
|
|
41055
|
-
|
|
41281
|
+
canonical5(path);
|
|
41056
41282
|
const rows = [], paths = [];
|
|
41057
41283
|
let metadataBytes = 0, steps = 0, links = 0, cursor = parse3(path).root, pending = path.slice(cursor.length).split(sep5);
|
|
41058
41284
|
function record4(path2, row) {
|
|
@@ -41077,7 +41303,7 @@ function trace(path) {
|
|
|
41077
41303
|
if (!component || component === ".")
|
|
41078
41304
|
continue;
|
|
41079
41305
|
if (component === "..") {
|
|
41080
|
-
cursor =
|
|
41306
|
+
cursor = dirname12(cursor);
|
|
41081
41307
|
continue;
|
|
41082
41308
|
}
|
|
41083
41309
|
const candidate = join19(cursor, component);
|
|
@@ -41097,11 +41323,11 @@ function trace(path) {
|
|
|
41097
41323
|
if (!target || target.includes("\x00") || Buffer.byteLength(target) > AGENT_POLICY_LIMITS.pathCharacters || !after.isSymbolicLink() || JSON.stringify(identity4(stat, true)) !== JSON.stringify(identity4(after, true)))
|
|
41098
41324
|
throw new Error("Discovery link changed during read");
|
|
41099
41325
|
record4(candidate, { type: "link", target, ...identity4(stat, true) });
|
|
41100
|
-
if (
|
|
41326
|
+
if (isAbsolute13(target)) {
|
|
41101
41327
|
cursor = parse3(target).root;
|
|
41102
41328
|
root();
|
|
41103
41329
|
}
|
|
41104
|
-
const remainder =
|
|
41330
|
+
const remainder = isAbsolute13(target) ? target.slice(parse3(target).root.length) : target;
|
|
41105
41331
|
pending = [...remainder.split(sep5), ...pending];
|
|
41106
41332
|
if (pending.length + steps > AGENT_POLICY_LIMITS.discoveryPathSteps)
|
|
41107
41333
|
throw new Error("Discovery path step limit exceeded");
|
|
@@ -41144,15 +41370,15 @@ function hashDiscoveryPathFile(path, budget2, changes) {
|
|
|
41144
41370
|
const after = trace(path);
|
|
41145
41371
|
if (JSON.stringify(before.rows) !== JSON.stringify(after.rows) || before.file !== after.file)
|
|
41146
41372
|
throw new Error("Discovery path input changed during read");
|
|
41147
|
-
return
|
|
41373
|
+
return createHash16("sha256").update(JSON.stringify({ version: 1, path, rows: before.rows, content })).digest("hex");
|
|
41148
41374
|
}
|
|
41149
41375
|
|
|
41150
41376
|
// src/lib/claude-plugin-manifest-witness.ts
|
|
41151
|
-
import { createHash as
|
|
41377
|
+
import { createHash as createHash17 } from "crypto";
|
|
41152
41378
|
var CLAUDE_PLUGIN_MANIFEST_LIMITS = Object.freeze({ bytes: 1024 * 1024, depth: 32, nodes: 65536, stringCharacters: 16384 });
|
|
41153
|
-
function requireValue(value,
|
|
41379
|
+
function requireValue(value, reason2) {
|
|
41154
41380
|
if (!value)
|
|
41155
|
-
throw new Error("Claude plugin manifest " +
|
|
41381
|
+
throw new Error("Claude plugin manifest " + reason2);
|
|
41156
41382
|
}
|
|
41157
41383
|
function parse4(text2) {
|
|
41158
41384
|
requireValue(Buffer.byteLength(text2, "utf8") <= CLAUDE_PLUGIN_MANIFEST_LIMITS.bytes, "exceeds its byte limit");
|
|
@@ -41228,7 +41454,7 @@ function parse4(text2) {
|
|
|
41228
41454
|
requireValue(at === text2.length && root.kind === "object", "requires a JSON object without trailing content");
|
|
41229
41455
|
return root;
|
|
41230
41456
|
}
|
|
41231
|
-
function
|
|
41457
|
+
function canonical6(value) {
|
|
41232
41458
|
if (value.kind === "string")
|
|
41233
41459
|
return JSON.stringify(value.value);
|
|
41234
41460
|
if (value.kind === "number")
|
|
@@ -41236,19 +41462,19 @@ function canonical5(value) {
|
|
|
41236
41462
|
if (value.kind === "literal")
|
|
41237
41463
|
return value.value;
|
|
41238
41464
|
if (value.kind === "array")
|
|
41239
|
-
return "[" + value.items.map(
|
|
41240
|
-
return "{" + value.entries.map(([key, item]) => JSON.stringify(key) + ":" +
|
|
41465
|
+
return "[" + value.items.map(canonical6).join(",") + "]";
|
|
41466
|
+
return "{" + value.entries.map(([key, item]) => JSON.stringify(key) + ":" + canonical6(item)).join(",") + "}";
|
|
41241
41467
|
}
|
|
41242
41468
|
var DESCRIPTIVE_FIELDS = new Set(["description", "version", "author", "homepage", "repository", "license", "keywords"]);
|
|
41243
|
-
function validateText(value,
|
|
41244
|
-
requireValue(value?.kind === "string" && value.value.length <= CLAUDE_PLUGIN_MANIFEST_LIMITS.stringCharacters, "has an invalid " +
|
|
41469
|
+
function validateText(value, field2) {
|
|
41470
|
+
requireValue(value?.kind === "string" && value.value.length <= CLAUDE_PLUGIN_MANIFEST_LIMITS.stringCharacters, "has an invalid " + field2 + " field");
|
|
41245
41471
|
}
|
|
41246
41472
|
function validateDescriptiveFields(manifest) {
|
|
41247
41473
|
const values = new Map(manifest.entries);
|
|
41248
|
-
for (const
|
|
41249
|
-
const value = values.get(
|
|
41474
|
+
for (const field2 of ["description", "version", "homepage", "license"]) {
|
|
41475
|
+
const value = values.get(field2);
|
|
41250
41476
|
if (value !== undefined)
|
|
41251
|
-
validateText(value,
|
|
41477
|
+
validateText(value, field2);
|
|
41252
41478
|
}
|
|
41253
41479
|
const author = values.get("author");
|
|
41254
41480
|
if (author !== undefined) {
|
|
@@ -41273,10 +41499,10 @@ function hashClaudePluginManifest(text2) {
|
|
|
41273
41499
|
const manifest = parse4(text2);
|
|
41274
41500
|
validateDescriptiveFields(manifest);
|
|
41275
41501
|
const discovery = { kind: "object", entries: manifest.entries.filter(([key]) => !DESCRIPTIVE_FIELDS.has(key)) };
|
|
41276
|
-
return
|
|
41502
|
+
return createHash17("sha256").update(canonical6(discovery)).digest("hex");
|
|
41277
41503
|
}
|
|
41278
41504
|
function projectReviewedClaudePluginManifest(text2, reviewedSha256) {
|
|
41279
|
-
if (!/^[a-f0-9]{64}$/.test(reviewedSha256) ||
|
|
41505
|
+
if (!/^[a-f0-9]{64}$/.test(reviewedSha256) || createHash17("sha256").update(text2).digest("hex") !== reviewedSha256) {
|
|
41280
41506
|
throw new Error("Reviewed Claude plugin manifest changed before semantic projection");
|
|
41281
41507
|
}
|
|
41282
41508
|
return hashClaudePluginManifest(text2);
|
|
@@ -41284,14 +41510,14 @@ function projectReviewedClaudePluginManifest(text2, reviewedSha256) {
|
|
|
41284
41510
|
|
|
41285
41511
|
// src/lib/plugin-discovery.ts
|
|
41286
41512
|
import { closeSync as closeSync14, constants as constants11, fstatSync as fstatSync14, lstatSync as lstatSync17, openSync as openSync14, opendirSync as opendirSync4, readSync as readSync9 } from "fs";
|
|
41287
|
-
import { basename as
|
|
41513
|
+
import { basename as basename7, dirname as dirname14, isAbsolute as isAbsolute17, join as join24, resolve as resolve15 } from "path";
|
|
41288
41514
|
|
|
41289
41515
|
// src/lib/plugin-admission.ts
|
|
41290
41516
|
import { homedir as homedir2 } from "os";
|
|
41291
|
-
import { isAbsolute as
|
|
41517
|
+
import { isAbsolute as isAbsolute16, join as join23, resolve as resolve14 } from "path";
|
|
41292
41518
|
|
|
41293
41519
|
// src/lib/plugin-projection.ts
|
|
41294
|
-
import { createHash as
|
|
41520
|
+
import { createHash as createHash18 } from "crypto";
|
|
41295
41521
|
import { posix as posix2 } from "path";
|
|
41296
41522
|
var PLUGIN_PROJECTION_MANIFEST = "plugin-projection.json";
|
|
41297
41523
|
var PLUGIN_PROJECTION_LIMITS = Object.freeze({ files: 1024, bytes: 64 * 1024 * 1024, fileBytes: 16 * 1024 * 1024, metadataBytes: 512 * 1024, registrations: 64, history: 128 });
|
|
@@ -41302,7 +41528,7 @@ function pluginNeed(value, message) {
|
|
|
41302
41528
|
if (!value)
|
|
41303
41529
|
pluginRefusal(message);
|
|
41304
41530
|
}
|
|
41305
|
-
var pluginHash = (bytes) =>
|
|
41531
|
+
var pluginHash = (bytes) => createHash18("sha256").update(bytes).digest("hex");
|
|
41306
41532
|
function pluginObject(value) {
|
|
41307
41533
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
41308
41534
|
}
|
|
@@ -41490,9 +41716,9 @@ function buildPluginProjection(entries) {
|
|
|
41490
41716
|
}
|
|
41491
41717
|
|
|
41492
41718
|
// src/lib/plugin-projection-store.ts
|
|
41493
|
-
import { createHash as
|
|
41719
|
+
import { createHash as createHash19, randomUUID as randomUUID3 } from "crypto";
|
|
41494
41720
|
import { constants as constants10, closeSync as closeSync13, fchmodSync, fstatSync as fstatSync13, fsyncSync as fsyncSync3, linkSync as linkSync2, lstatSync as lstatSync15, mkdirSync as mkdirSync5, openSync as openSync13, opendirSync as opendirSync3, readSync as readSync8, renameSync as renameSync3, rmdirSync as rmdirSync2, rmSync, unlinkSync as unlinkSync4, writeSync as writeSync2 } from "fs";
|
|
41495
|
-
import { dirname as
|
|
41721
|
+
import { dirname as dirname13, isAbsolute as isAbsolute14, join as join20, parse as parse6, resolve as resolve13 } from "path";
|
|
41496
41722
|
var READ_FLAGS = constants10.O_RDONLY | constants10.O_NOFOLLOW | constants10.O_NONBLOCK;
|
|
41497
41723
|
var WRITE_FLAGS = constants10.O_WRONLY | constants10.O_CREAT | constants10.O_EXCL | constants10.O_NOFOLLOW | constants10.O_NONBLOCK;
|
|
41498
41724
|
var uid = () => typeof process.getuid === "function" ? BigInt(process.getuid()) : undefined;
|
|
@@ -41506,8 +41732,8 @@ function stat(path) {
|
|
|
41506
41732
|
return pluginRefusal("Cannot inspect plugin filesystem entry");
|
|
41507
41733
|
}
|
|
41508
41734
|
}
|
|
41509
|
-
function
|
|
41510
|
-
pluginNeed(typeof path === "string" && path.length <= 8192 &&
|
|
41735
|
+
function canonical7(path) {
|
|
41736
|
+
pluginNeed(typeof path === "string" && path.length <= 8192 && isAbsolute14(path) && resolve13(path) === path && !/[\x00-\x1f\x7f]/.test(path), "Plugin storage paths must be canonical absolute paths");
|
|
41511
41737
|
}
|
|
41512
41738
|
function owner(stats, system = false) {
|
|
41513
41739
|
const current = uid();
|
|
@@ -41517,8 +41743,8 @@ function same3(left, right, identityOnly = false) {
|
|
|
41517
41743
|
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");
|
|
41518
41744
|
}
|
|
41519
41745
|
function ancestors(path, create = false) {
|
|
41520
|
-
|
|
41521
|
-
const result = [], parent =
|
|
41746
|
+
canonical7(path);
|
|
41747
|
+
const result = [], parent = dirname13(path), filesystemRoot = parse6(parent).root;
|
|
41522
41748
|
let current = filesystemRoot;
|
|
41523
41749
|
for (const segment of ["", ...parent.slice(filesystemRoot.length).split("/").filter(Boolean)]) {
|
|
41524
41750
|
if (segment)
|
|
@@ -41546,7 +41772,7 @@ function verifyAncestors(chain, identityOnly = true) {
|
|
|
41546
41772
|
}
|
|
41547
41773
|
function privateParent(path) {
|
|
41548
41774
|
const chain = ancestors(path, true), parent = chain.at(-1);
|
|
41549
|
-
pluginNeed(parent && parent.path ===
|
|
41775
|
+
pluginNeed(parent && parent.path === dirname13(path), "Plugin storage parent is unavailable");
|
|
41550
41776
|
owner(parent.stat);
|
|
41551
41777
|
pluginNeed((parent.stat.mode & 0o7777n) === 0o700n, "Plugin storage parent must have mode 0700");
|
|
41552
41778
|
return chain;
|
|
@@ -41832,7 +42058,7 @@ function pluginExecutableDigest(path) {
|
|
|
41832
42058
|
const opened = fstatSync13(fd, { bigint: true });
|
|
41833
42059
|
same3(before, opened);
|
|
41834
42060
|
fileShape(opened, maximum, "executable");
|
|
41835
|
-
const hash2 =
|
|
42061
|
+
const hash2 = createHash19("sha256"), buffer = new Uint8Array(64 * 1024);
|
|
41836
42062
|
let remaining = Number(opened.size);
|
|
41837
42063
|
while (remaining > 0) {
|
|
41838
42064
|
const count = readSync8(fd, buffer, 0, Math.min(buffer.byteLength, remaining), null);
|
|
@@ -41857,7 +42083,7 @@ function pluginExecutableDigest(path) {
|
|
|
41857
42083
|
|
|
41858
42084
|
// src/lib/skill-validation.ts
|
|
41859
42085
|
import { existsSync as existsSync5, lstatSync as lstatSync16, readFileSync as readFileSync14, readdirSync as readdirSync6, statSync as statSync6 } from "fs";
|
|
41860
|
-
import { isAbsolute as
|
|
42086
|
+
import { isAbsolute as isAbsolute15, join as join22, normalize as normalize3 } from "path";
|
|
41861
42087
|
|
|
41862
42088
|
// src/lib/hosted-skill-set.ts
|
|
41863
42089
|
import { existsSync as existsSync4, readFileSync as readFileSync13, readdirSync as readdirSync5, statSync as statSync5 } from "fs";
|
|
@@ -41961,7 +42187,7 @@ function sortMessages(messages) {
|
|
|
41961
42187
|
return [...messages].sort((a, b) => a.code.localeCompare(b.code) || a.message.localeCompare(b.message));
|
|
41962
42188
|
}
|
|
41963
42189
|
function isSafeRelativePath(value) {
|
|
41964
|
-
if (!value.trim() ||
|
|
42190
|
+
if (!value.trim() || isAbsolute15(value))
|
|
41965
42191
|
return false;
|
|
41966
42192
|
const normalized = normalize3(value).replace(/\\/g, "/");
|
|
41967
42193
|
return normalized !== ".." && !normalized.startsWith("../") && !normalized.includes("/../");
|
|
@@ -42326,7 +42552,7 @@ function validatePluginTarget(value) {
|
|
|
42326
42552
|
for (const registration of value.registrations) {
|
|
42327
42553
|
pluginKeys(registration, ["scope", "projectPath"]);
|
|
42328
42554
|
pluginNeed(registration.scope === "user" || registration.scope === "project", "Unsupported plugin registration scope");
|
|
42329
|
-
pluginNeed(registration.scope === "user" ? registration.projectPath === null : typeof registration.projectPath === "string" &&
|
|
42555
|
+
pluginNeed(registration.scope === "user" ? registration.projectPath === null : typeof registration.projectPath === "string" && isAbsolute16(registration.projectPath) && resolve14(registration.projectPath) === registration.projectPath, "Plugin scope requires its exact project path");
|
|
42330
42556
|
const key = JSON.stringify([registration.scope, registration.projectPath]);
|
|
42331
42557
|
pluginNeed(!scopes.has(key), "Duplicate plugin registration scope");
|
|
42332
42558
|
scopes.add(key);
|
|
@@ -42334,7 +42560,7 @@ function validatePluginTarget(value) {
|
|
|
42334
42560
|
for (const key of ["native", "resolver"]) {
|
|
42335
42561
|
pluginKeys(value[key], key === "native" ? ["version", "executable", "digest"] : ["executable", "digest"]);
|
|
42336
42562
|
pluginText(value[key].executable);
|
|
42337
|
-
pluginNeed(
|
|
42563
|
+
pluginNeed(isAbsolute16(value[key].executable) && resolve14(value[key].executable) === value[key].executable, "Plugin executable must have a canonical absolute path");
|
|
42338
42564
|
pluginDigest(value[key].digest);
|
|
42339
42565
|
}
|
|
42340
42566
|
pluginNeed(["2.1.274", "2.1.276"].includes(value.native.version), "Plugin admission requires a certified Claude command-source runtime (2.1.274 or 2.1.276)");
|
|
@@ -42479,14 +42705,14 @@ function validatePlan(value) {
|
|
|
42479
42705
|
pluginNeed(observedEvidenceDigest(plan.observation) === plan.evidenceDigest, "Plugin receipt observed evidence changed");
|
|
42480
42706
|
pluginNeed(identityDigest(plan) === plan.planDigest, "Plugin receipt immutable identity changed");
|
|
42481
42707
|
}
|
|
42482
|
-
var
|
|
42708
|
+
var quote2 = (value) => `'${value.replaceAll("'", "'\\''")}'`;
|
|
42483
42709
|
var resolverGuard = 'exec 9<"$1"; actual=$(/usr/bin/sha256sum /proc/self/fd/9); actual=${actual%% *}; [ "sha256:$actual" = "$2" ]; exec /proc/self/fd/9 integration plugin resolve --binding "$3"';
|
|
42484
42710
|
function pluginResolverCommand(binding) {
|
|
42485
|
-
return `${
|
|
42711
|
+
return `${quote2("/bin/sh")} -eu -c ${quote2(resolverGuard)} plugin-resolver ${quote2(binding.target.resolver.executable)} ${quote2(binding.target.resolver.digest)} ${quote2(bindingId(binding))}`;
|
|
42486
42712
|
}
|
|
42487
42713
|
function root(options) {
|
|
42488
42714
|
const path = options.storeRoot ?? pluginAdmissionRoot();
|
|
42489
|
-
pluginNeed(
|
|
42715
|
+
pluginNeed(isAbsolute16(path) && resolve14(path) === path, "Invalid plugin admission store root");
|
|
42490
42716
|
return path;
|
|
42491
42717
|
}
|
|
42492
42718
|
function pluginBindingPath(storeRoot, id2) {
|
|
@@ -42691,15 +42917,15 @@ function validateManagedPluginWitnesses(value) {
|
|
|
42691
42917
|
pluginNeed(typeof item.bindingId === "string" && /^[a-f0-9]{64}$/.test(item.bindingId) && !seen.has(item.bindingId), "Invalid or duplicate managed plugin witness");
|
|
42692
42918
|
seen.add(item.bindingId);
|
|
42693
42919
|
pluginText(item.storeRoot);
|
|
42694
|
-
pluginNeed(
|
|
42920
|
+
pluginNeed(isAbsolute17(item.storeRoot) && resolve15(item.storeRoot) === item.storeRoot, "Invalid plugin receipt store path");
|
|
42695
42921
|
}
|
|
42696
42922
|
}
|
|
42697
42923
|
function safe3(path) {
|
|
42698
42924
|
pluginText(path);
|
|
42699
|
-
pluginNeed(
|
|
42700
|
-
for (let at = path;; at =
|
|
42925
|
+
pluginNeed(isAbsolute17(path) && resolve15(path) === path, "Invalid plugin registry path");
|
|
42926
|
+
for (let at = path;; at = dirname14(at)) {
|
|
42701
42927
|
pluginNeed(!lstatSync17(at, { throwIfNoEntry: false })?.isSymbolicLink(), "Plugin registry path traverses a symlink");
|
|
42702
|
-
if (at ===
|
|
42928
|
+
if (at === dirname14(at))
|
|
42703
42929
|
break;
|
|
42704
42930
|
}
|
|
42705
42931
|
}
|
|
@@ -42749,7 +42975,7 @@ function hashManagedPluginRegistry(path, managed) {
|
|
|
42749
42975
|
seen.add(target.pluginId);
|
|
42750
42976
|
const rows = plugins[target.pluginId];
|
|
42751
42977
|
pluginNeed(Array.isArray(rows) && rows.length === target.registrations.length, "Managed plugin registration membership changed");
|
|
42752
|
-
const [name, market] = target.pluginId.split("@"), cacheRoot = join24(
|
|
42978
|
+
const [name, market] = target.pluginId.split("@"), cacheRoot = join24(dirname14(path), "cache", market, name);
|
|
42753
42979
|
const scopes = new Set, approvals = new Map, currentFiles = new Map;
|
|
42754
42980
|
plugins[target.pluginId] = rows.map((row) => {
|
|
42755
42981
|
pluginNeed(pluginObject(row), "Invalid managed plugin registration");
|
|
@@ -42765,7 +42991,7 @@ function hashManagedPluginRegistry(path, managed) {
|
|
|
42765
42991
|
pluginNeed(/^(?:[A-Za-z0-9][A-Za-z0-9._+-]*-)?[a-f0-9]{12}$/.test(row.version) && row.installPath === join24(cacheRoot, row.version), "Managed plugin cache path or version is outside its registration");
|
|
42766
42992
|
const approval = (producer) => {
|
|
42767
42993
|
pluginText(producer);
|
|
42768
|
-
const digest2 = `sha256:${
|
|
42994
|
+
const digest2 = `sha256:${basename7(producer)}`;
|
|
42769
42995
|
const receipt2 = readPluginAdmissionReceipt(witness.storeRoot, witness.bindingId, digest2);
|
|
42770
42996
|
pluginNeed(receipt2.materializedPath === producer, "Managed producer path is not an approved immutable projection");
|
|
42771
42997
|
if (!verified.has(producer)) {
|
|
@@ -42827,39 +43053,39 @@ function captureManagedPluginRegistry(path, managedPlugins) {
|
|
|
42827
43053
|
}
|
|
42828
43054
|
|
|
42829
43055
|
// src/lib/claude-marketplace-registry.ts
|
|
42830
|
-
import { createHash as
|
|
43056
|
+
import { createHash as createHash20 } from "crypto";
|
|
42831
43057
|
import { closeSync as closeSync15, constants as constants12, fstatSync as fstatSync15, lstatSync as lstatSync18, openSync as openSync15, readSync as readSync10 } from "fs";
|
|
42832
|
-
import { basename as
|
|
43058
|
+
import { basename as basename8, dirname as dirname15, isAbsolute as isAbsolute18, resolve as resolve16 } from "path";
|
|
42833
43059
|
var CLAUDE_MARKETPLACE_REGISTRY_LIMITS = Object.freeze({ bytes: 1024 * 1024, rows: 1024, depth: 32, nodes: 65536, stringCharacters: 16384, pathCharacters: 4096 });
|
|
42834
|
-
function
|
|
43060
|
+
function need6(value, reason2) {
|
|
42835
43061
|
if (!value)
|
|
42836
|
-
throw new Error(`Claude marketplace registry ${
|
|
43062
|
+
throw new Error(`Claude marketplace registry ${reason2}`);
|
|
42837
43063
|
}
|
|
42838
43064
|
function absolutePath3(value) {
|
|
42839
|
-
|
|
43065
|
+
need6(typeof value === "string" && value.length > 0 && value.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute18(value) && resolve16(value) === value, "requires a normalized absolute path");
|
|
42840
43066
|
}
|
|
42841
43067
|
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;
|
|
42842
43068
|
function parents2(path) {
|
|
42843
43069
|
const result = [];
|
|
42844
|
-
for (let at =
|
|
43070
|
+
for (let at = dirname15(path);; at = dirname15(at)) {
|
|
42845
43071
|
const stat2 = lstatSync18(at, { bigint: true });
|
|
42846
|
-
|
|
43072
|
+
need6(stat2.isDirectory() && !stat2.isSymbolicLink(), "path traverses a symlink or non-directory");
|
|
42847
43073
|
result.push([at, stat2]);
|
|
42848
|
-
if (at ===
|
|
43074
|
+
if (at === dirname15(at))
|
|
42849
43075
|
return result;
|
|
42850
43076
|
}
|
|
42851
43077
|
}
|
|
42852
43078
|
function readRegistry2(path, budget2) {
|
|
42853
43079
|
absolutePath3(path);
|
|
42854
|
-
|
|
42855
|
-
|
|
43080
|
+
need6(basename8(path) === "known_marketplaces.json", "requires known_marketplaces.json");
|
|
43081
|
+
need6(Number.isSafeInteger(budget2.remaining) && budget2.remaining >= 0, "has an invalid byte budget");
|
|
42856
43082
|
const ancestors2 = parents2(path), initial = lstatSync18(path, { bigint: true });
|
|
42857
|
-
|
|
42858
|
-
|
|
43083
|
+
need6(initial.isFile() && !initial.isSymbolicLink() && initial.size <= BigInt(CLAUDE_MARKETPLACE_REGISTRY_LIMITS.bytes), "is not a bounded regular file");
|
|
43084
|
+
need6(initial.size <= BigInt(budget2.remaining), "exceeds its aggregate byte limit");
|
|
42859
43085
|
const fd = openSync15(path, constants12.O_RDONLY | constants12.O_NOFOLLOW | constants12.O_NONBLOCK);
|
|
42860
43086
|
try {
|
|
42861
43087
|
const opened = fstatSync15(fd, { bigint: true });
|
|
42862
|
-
|
|
43088
|
+
need6(opened.isFile() && sameFile2(initial, opened), "changed during open");
|
|
42863
43089
|
const bytes = Buffer.alloc(Number(opened.size) + 1);
|
|
42864
43090
|
let length = 0;
|
|
42865
43091
|
while (length < bytes.length) {
|
|
@@ -42869,10 +43095,10 @@ function readRegistry2(path, budget2) {
|
|
|
42869
43095
|
length += count;
|
|
42870
43096
|
}
|
|
42871
43097
|
const after = fstatSync15(fd, { bigint: true }), current = lstatSync18(path, { bigint: true });
|
|
42872
|
-
|
|
43098
|
+
need6(current.isFile() && sameFile2(opened, after) && sameFile2(after, current) && BigInt(length) === opened.size, "changed during read");
|
|
42873
43099
|
for (const [ancestor, before] of ancestors2) {
|
|
42874
43100
|
const now = lstatSync18(ancestor, { bigint: true });
|
|
42875
|
-
|
|
43101
|
+
need6(now.isDirectory() && before.dev === now.dev && before.ino === now.ino && before.mode === now.mode, "parent changed during read");
|
|
42876
43102
|
}
|
|
42877
43103
|
budget2.remaining -= length;
|
|
42878
43104
|
try {
|
|
@@ -42892,7 +43118,7 @@ function parse7(text2) {
|
|
|
42892
43118
|
at++;
|
|
42893
43119
|
};
|
|
42894
43120
|
function string() {
|
|
42895
|
-
|
|
43121
|
+
need6(text2[at] === '"', "contains invalid JSON");
|
|
42896
43122
|
const start = at++;
|
|
42897
43123
|
while (at < text2.length) {
|
|
42898
43124
|
const character = text2[at++];
|
|
@@ -42903,7 +43129,7 @@ function parse7(text2) {
|
|
|
42903
43129
|
} catch {
|
|
42904
43130
|
throw new Error("Claude marketplace registry contains invalid JSON string");
|
|
42905
43131
|
}
|
|
42906
|
-
|
|
43132
|
+
need6(value2.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.stringCharacters, "exceeds its string limit");
|
|
42907
43133
|
return value2;
|
|
42908
43134
|
}
|
|
42909
43135
|
if (character === "\\")
|
|
@@ -42912,7 +43138,7 @@ function parse7(text2) {
|
|
|
42912
43138
|
throw new Error("Claude marketplace registry contains an unterminated JSON string");
|
|
42913
43139
|
}
|
|
42914
43140
|
function value(depth) {
|
|
42915
|
-
|
|
43141
|
+
need6(depth <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.depth && ++nodes <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.nodes, "exceeds its nesting or node limit");
|
|
42916
43142
|
space();
|
|
42917
43143
|
const character = text2[at];
|
|
42918
43144
|
if (character === '"')
|
|
@@ -42926,17 +43152,17 @@ function parse7(text2) {
|
|
|
42926
43152
|
if (object6) {
|
|
42927
43153
|
space();
|
|
42928
43154
|
const key = string();
|
|
42929
|
-
|
|
43155
|
+
need6(!keys2.has(key), "contains a duplicate JSON key");
|
|
42930
43156
|
keys2.add(key);
|
|
42931
43157
|
space();
|
|
42932
|
-
|
|
43158
|
+
need6(text2[at++] === ":", "contains invalid JSON");
|
|
42933
43159
|
entries.push([key, value(depth + 1)]);
|
|
42934
43160
|
} else
|
|
42935
43161
|
items.push(value(depth + 1));
|
|
42936
43162
|
space();
|
|
42937
43163
|
if (text2[at] === end)
|
|
42938
43164
|
break;
|
|
42939
|
-
|
|
43165
|
+
need6(text2[at++] === ",", "contains invalid JSON");
|
|
42940
43166
|
}
|
|
42941
43167
|
at++;
|
|
42942
43168
|
return object6 ? { kind: "object", entries } : { kind: "array", items };
|
|
@@ -42948,96 +43174,112 @@ function parse7(text2) {
|
|
|
42948
43174
|
}
|
|
42949
43175
|
numberPattern.lastIndex = at;
|
|
42950
43176
|
const number = numberPattern.exec(text2);
|
|
42951
|
-
|
|
43177
|
+
need6(number, "contains invalid JSON");
|
|
42952
43178
|
at += number[0].length;
|
|
42953
43179
|
return { kind: "number", value: number[0] };
|
|
42954
43180
|
}
|
|
42955
43181
|
const root2 = value(0);
|
|
42956
43182
|
space();
|
|
42957
|
-
|
|
42958
|
-
|
|
43183
|
+
need6(at === text2.length && root2.kind === "object", "requires a JSON object without trailing content");
|
|
43184
|
+
need6(root2.entries.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.rows, "exceeds its marketplace row limit");
|
|
42959
43185
|
return root2;
|
|
42960
43186
|
}
|
|
42961
43187
|
function exactKeys2(value, keys2) {
|
|
42962
43188
|
return value?.kind === "object" && value.entries.length === keys2.length && value.entries.every(([key]) => keys2.includes(key));
|
|
42963
43189
|
}
|
|
42964
|
-
var
|
|
43190
|
+
var field2 = (object6, key) => object6.entries.find(([name]) => name === key)?.[1];
|
|
42965
43191
|
function textField(value) {
|
|
42966
|
-
|
|
43192
|
+
need6(value?.kind === "string" && value.value.length > 0 && !/[\x00-\x1f\x7f]/.test(value.value), "contains an invalid recognized field");
|
|
42967
43193
|
return value.value;
|
|
42968
43194
|
}
|
|
42969
43195
|
function normalizeRow(row, version = 1) {
|
|
42970
43196
|
if (!exactKeys2(row, ["source", "installLocation", "lastUpdated"])) {
|
|
42971
43197
|
if (version !== 2 || !exactKeys2(row, ["source", "installLocation", "lastUpdated", "autoUpdate"]))
|
|
42972
43198
|
return;
|
|
42973
|
-
const autoUpdate =
|
|
42974
|
-
|
|
43199
|
+
const autoUpdate = field2(row, "autoUpdate");
|
|
43200
|
+
need6(autoUpdate?.kind === "literal" && (autoUpdate.value === "true" || autoUpdate.value === "false"), "contains an invalid automatic-update preference");
|
|
42975
43201
|
}
|
|
42976
|
-
const source =
|
|
43202
|
+
const source = field2(row, "source");
|
|
42977
43203
|
if (source?.kind !== "object")
|
|
42978
43204
|
return;
|
|
42979
|
-
const type =
|
|
43205
|
+
const type = field2(source, "source");
|
|
42980
43206
|
if (type?.kind !== "string" || !["github", "directory"].includes(type.value))
|
|
42981
43207
|
return;
|
|
42982
43208
|
const location = type.value === "github" ? "repo" : "path";
|
|
42983
43209
|
if (!exactKeys2(source, ["source", location]))
|
|
42984
43210
|
return;
|
|
42985
|
-
const sourceLocation = textField(
|
|
43211
|
+
const sourceLocation = textField(field2(source, location));
|
|
42986
43212
|
if (type.value === "directory")
|
|
42987
43213
|
absolutePath3(sourceLocation);
|
|
42988
|
-
absolutePath3(textField(
|
|
42989
|
-
const updated = textField(
|
|
42990
|
-
|
|
43214
|
+
absolutePath3(textField(field2(row, "installLocation")));
|
|
43215
|
+
const updated = textField(field2(row, "lastUpdated"));
|
|
43216
|
+
need6(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/.test(updated), "contains an invalid recognized update timestamp");
|
|
42991
43217
|
const millis = Date.parse(updated);
|
|
42992
|
-
|
|
43218
|
+
need6(Number.isFinite(millis) && new Date(millis).toISOString() === updated, "contains an invalid recognized update timestamp");
|
|
42993
43219
|
row.entries = row.entries.map(([key, value]) => [key, key === "lastUpdated" ? { kind: "validated-update-time" } : value]);
|
|
42994
43220
|
}
|
|
42995
43221
|
function captureClaudeMarketplaceRegistry(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
42996
43222
|
const value = parse7(readRegistry2(path, budget2));
|
|
42997
43223
|
for (const [, row] of value.entries)
|
|
42998
43224
|
normalizeRow(row);
|
|
42999
|
-
const sha2562 =
|
|
43225
|
+
const sha2562 = createHash20("sha256").update("hasna.skills.claude-marketplace-registry.v1\x00").update(JSON.stringify(value)).digest("hex");
|
|
43000
43226
|
return { path, hashMode: "claude-marketplace-registry", sha256: sha2562 };
|
|
43001
43227
|
}
|
|
43002
43228
|
function captureClaudeMarketplaceRegistryV2(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
43003
43229
|
const value = parse7(readRegistry2(path, budget2));
|
|
43004
43230
|
for (const [, row] of value.entries)
|
|
43005
43231
|
normalizeRow(row, 2);
|
|
43006
|
-
const sha2562 =
|
|
43232
|
+
const sha2562 = createHash20("sha256").update("hasna.skills.claude-marketplace-registry.v2\x00").update(JSON.stringify(value)).digest("hex");
|
|
43007
43233
|
return { path, hashMode: "claude-marketplace-registry-v2", sha256: sha2562 };
|
|
43008
43234
|
}
|
|
43009
43235
|
|
|
43010
43236
|
// src/lib/codex-hook-discovery-recovery.ts
|
|
43011
|
-
import { createHash as
|
|
43237
|
+
import { createHash as createHash22 } from "crypto";
|
|
43012
43238
|
|
|
43013
43239
|
// src/lib/codex-hook-trust-files.ts
|
|
43014
|
-
import { closeSync as closeSync16, constants as constants13, fstatSync as fstatSync16, fsyncSync as fsyncSync4, lstatSync as lstatSync19, openSync as openSync16, readSync as readSync11, writeFileSync as writeFileSync4 } from "fs";
|
|
43015
|
-
import { createHash as
|
|
43016
|
-
import { dirname as
|
|
43017
|
-
function
|
|
43240
|
+
import { closeSync as closeSync16, constants as constants13, fstatSync as fstatSync16, fsyncSync as fsyncSync4, lstatSync as lstatSync19, openSync as openSync16, readlinkSync as readlinkSync5, readSync as readSync11, writeFileSync as writeFileSync4 } from "fs";
|
|
43241
|
+
import { createHash as createHash21 } from "crypto";
|
|
43242
|
+
import { dirname as dirname16, isAbsolute as isAbsolute19, resolve as resolve17 } from "path";
|
|
43243
|
+
function need7(value, code) {
|
|
43018
43244
|
if (!value)
|
|
43019
43245
|
throw new Error(`CODEX_HOOK_TRUST_${code}`);
|
|
43020
43246
|
}
|
|
43021
43247
|
var sameStat = (a, b) => ["dev", "ino", "uid", "nlink", "mode", "size", "mtimeNs", "ctimeNs"].every((key) => a[key] === b[key]);
|
|
43248
|
+
function trustedAncestorOwner(uid2) {
|
|
43249
|
+
return BigInt(uid2) === 0n || BigInt(uid2) === BigInt(process.getuid());
|
|
43250
|
+
}
|
|
43022
43251
|
function safeParents(file) {
|
|
43023
|
-
for (let p =
|
|
43252
|
+
for (let p = dirname16(file);; p = dirname16(p)) {
|
|
43024
43253
|
const s = lstatSync19(p);
|
|
43025
|
-
|
|
43026
|
-
|
|
43027
|
-
if (
|
|
43254
|
+
need7(s.isDirectory() && !s.isSymbolicLink() && trustedAncestorOwner(s.uid), "UNSAFE_PARENT");
|
|
43255
|
+
need7((s.mode & 18) === 0 || s.uid === 0 && (s.mode & 512) !== 0, "UNSAFE_PARENT");
|
|
43256
|
+
if (dirname16(p) === p)
|
|
43028
43257
|
break;
|
|
43029
43258
|
}
|
|
43030
43259
|
}
|
|
43260
|
+
function directAliasTarget(link) {
|
|
43261
|
+
const text2 = readlinkSync5(link), parts = text2.split("/");
|
|
43262
|
+
let first = 0;
|
|
43263
|
+
if (isAbsolute19(text2))
|
|
43264
|
+
first = 1;
|
|
43265
|
+
else
|
|
43266
|
+
while (parts[first] === "..")
|
|
43267
|
+
first++;
|
|
43268
|
+
const names = parts.slice(first);
|
|
43269
|
+
if (!names.length || names.some((part) => part === "" || part === "." || part === ".."))
|
|
43270
|
+
return;
|
|
43271
|
+
return resolve17(dirname16(link), text2);
|
|
43272
|
+
}
|
|
43031
43273
|
function snapshot(file, privateFile = false, options = {}) {
|
|
43032
43274
|
const readOnlyPackage = options.readOnlyPackage === true && !privateFile;
|
|
43033
43275
|
safeParents(file);
|
|
43034
43276
|
const initial = lstatSync19(file, { bigint: true });
|
|
43035
|
-
|
|
43036
|
-
|
|
43277
|
+
need7(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");
|
|
43278
|
+
need7(initial.size <= 8n * 1024n * 1024n, "FILE_BOUND");
|
|
43037
43279
|
const fd = openSync16(file, constants13.O_RDONLY | constants13.O_NOFOLLOW | constants13.O_NONBLOCK);
|
|
43038
43280
|
try {
|
|
43039
43281
|
const before = fstatSync16(fd, { bigint: true });
|
|
43040
|
-
|
|
43282
|
+
need7(sameStat(initial, before), "INPUT_CHANGED");
|
|
43041
43283
|
const bytes = Buffer.alloc(Number(before.size) + 1);
|
|
43042
43284
|
let length = 0;
|
|
43043
43285
|
while (length < bytes.length) {
|
|
@@ -43046,16 +43288,16 @@ function snapshot(file, privateFile = false, options = {}) {
|
|
|
43046
43288
|
break;
|
|
43047
43289
|
length += n2;
|
|
43048
43290
|
}
|
|
43049
|
-
|
|
43291
|
+
need7(length === Number(before.size) && sameStat(before, fstatSync16(fd, { bigint: true })) && sameStat(before, lstatSync19(file, { bigint: true })), "INPUT_CHANGED");
|
|
43050
43292
|
const content = bytes.subarray(0, length), text2 = new TextDecoder("utf-8", { fatal: true }).decode(content);
|
|
43051
|
-
return { file, privateFile, readOnlyPackage, text: text2, bytes: content, stat: before, sha256:
|
|
43293
|
+
return { file, privateFile, readOnlyPackage, text: text2, bytes: content, stat: before, sha256: createHash21("sha256").update(content).digest("hex") };
|
|
43052
43294
|
} finally {
|
|
43053
43295
|
closeSync16(fd);
|
|
43054
43296
|
}
|
|
43055
43297
|
}
|
|
43056
43298
|
function unchanged2(before) {
|
|
43057
43299
|
const after = snapshot(before.file, before.privateFile, before.readOnlyPackage ? { readOnlyPackage: true } : {});
|
|
43058
|
-
|
|
43300
|
+
need7(sameStat(before.stat, after.stat) && after.sha256 === before.sha256, "INPUT_CHANGED");
|
|
43059
43301
|
}
|
|
43060
43302
|
|
|
43061
43303
|
// src/lib/codex-hook-additions-review.ts
|
|
@@ -43064,12 +43306,12 @@ var matchedEvents = { ...events, PreToolUse: ["preToolUse", "pre_tool_use"] };
|
|
|
43064
43306
|
var proofs = new WeakMap;
|
|
43065
43307
|
|
|
43066
43308
|
// src/lib/codex-hook-discovery-recovery.ts
|
|
43067
|
-
var sha3 = (text2) =>
|
|
43309
|
+
var sha3 = (text2) => createHash22("sha256").update(text2).digest("hex");
|
|
43068
43310
|
var fields = [...CODEX_DISCOVERY_PROJECTION_FIELDS];
|
|
43069
43311
|
var proofs2 = new WeakMap;
|
|
43070
43312
|
function assertCodexHookDiscoveryRecovery(binding, witness) {
|
|
43071
43313
|
const proof = proofs2.get(witness);
|
|
43072
|
-
|
|
43314
|
+
need7(!!proof && binding.agent === "codex" && witness.discoverySha256 === sha3(JSON.stringify(binding)), "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
|
|
43073
43315
|
unchanged2(proof.before);
|
|
43074
43316
|
unchanged2(proof.current);
|
|
43075
43317
|
proof.recheckAdditions();
|
|
@@ -43078,34 +43320,34 @@ function verifiesCodexHookDiscoverySource(binding, source, currentDigest, witnes
|
|
|
43078
43320
|
if (!witness || source.path !== witness.configPath || source.hashMode !== "bytes")
|
|
43079
43321
|
return false;
|
|
43080
43322
|
assertCodexHookDiscoveryRecovery(binding, witness);
|
|
43081
|
-
|
|
43323
|
+
need7(source.sha256 === witness.beforeSha256 && currentDigest === witness.currentSha256, "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
|
|
43082
43324
|
return true;
|
|
43083
43325
|
}
|
|
43084
43326
|
|
|
43085
43327
|
// src/lib/agent-sumi.ts
|
|
43086
43328
|
import { existsSync as existsSync6, lstatSync as lstatSync20, realpathSync as realpathSync8 } from "fs";
|
|
43087
|
-
import { join as join25, resolve as
|
|
43329
|
+
import { join as join25, resolve as resolve18 } from "path";
|
|
43088
43330
|
function sumiConfigDirectory(home, env = process.env) {
|
|
43089
43331
|
for (const key of ["SUMI_CONFIG", "SUMI_CONFIG_CONTENT"])
|
|
43090
43332
|
if (env[key] !== undefined)
|
|
43091
43333
|
throw new Error(`Sumi ${key} requires a dedicated discovery adapter; unset it before Skills integration`);
|
|
43092
43334
|
const selected = (key) => env[key]?.trim() ? env[key] : undefined;
|
|
43093
|
-
const expand = (value) =>
|
|
43335
|
+
const expand = (value) => resolve18(value === "~" ? home : value.startsWith("~/") ? join25(home, value.slice(2)) : value);
|
|
43094
43336
|
const explicit = selected("SUMI_CONFIG_DIR");
|
|
43095
43337
|
const xdg = selected("XDG_CONFIG_HOME");
|
|
43096
43338
|
const custom = selected("SUMI_HOME");
|
|
43097
|
-
const
|
|
43339
|
+
const canonical8 = explicit ? expand(explicit) : xdg ? join25(expand(xdg), "sumi") : join25(custom ? expand(custom) : join25(home, ".hasna-internal/sumi"), "config");
|
|
43098
43340
|
if (explicit || xdg || custom)
|
|
43099
|
-
return
|
|
43341
|
+
return canonical8;
|
|
43100
43342
|
const legacy = join25(home, ".config/sumi");
|
|
43101
|
-
const a = lstatSync20(
|
|
43102
|
-
if (a && b && realpathSync8(
|
|
43343
|
+
const a = lstatSync20(canonical8, { throwIfNoEntry: false }), b = lstatSync20(legacy, { throwIfNoEntry: false });
|
|
43344
|
+
if (a && b && realpathSync8(canonical8) !== realpathSync8(legacy))
|
|
43103
43345
|
throw new Error("Sumi config roots conflict; complete native home adoption before Skills integration");
|
|
43104
|
-
const path = a ?
|
|
43346
|
+
const path = a ? canonical8 : b ? legacy : canonical8;
|
|
43105
43347
|
if (!existsSync6(path))
|
|
43106
43348
|
return path;
|
|
43107
43349
|
const physical = realpathSync8(path);
|
|
43108
|
-
if ((a?.isSymbolicLink() || b?.isSymbolicLink()) && ![
|
|
43350
|
+
if ((a?.isSymbolicLink() || b?.isSymbolicLink()) && ![canonical8, legacy].includes(physical))
|
|
43109
43351
|
throw new Error("Sumi config alias must resolve to its canonical or legacy root");
|
|
43110
43352
|
return physical;
|
|
43111
43353
|
}
|
|
@@ -43205,7 +43447,38 @@ var SUMI_SKILL_PERMISSIONS = [
|
|
|
43205
43447
|
];
|
|
43206
43448
|
|
|
43207
43449
|
// src/lib/agent-discovery.ts
|
|
43208
|
-
var
|
|
43450
|
+
var DISCOVERY_RUNTIME_COMMANDS = Object.freeze({ gemini: "gemini" });
|
|
43451
|
+
var DISCOVERY_ROOT_UNRESOLVED = "DISCOVERY_ROOT_UNRESOLVED";
|
|
43452
|
+
function discoveryRootUnresolved(agent, command, detail) {
|
|
43453
|
+
return new Error(`${DISCOVERY_ROOT_UNRESOLVED}: ${agent} discovery cannot resolve its "${command}" executable: ${detail}. The reviewed discovery is unchanged; this is an environment gap, not drift.`);
|
|
43454
|
+
}
|
|
43455
|
+
function isDiscoveryRootUnresolved(error) {
|
|
43456
|
+
return error instanceof Error && error.message.startsWith(`${DISCOVERY_ROOT_UNRESOLVED}: `);
|
|
43457
|
+
}
|
|
43458
|
+
var quotedPath = (path) => JSON.stringify(path).replace(/[^\x20-\x7e]/g, (character) => `\\u${character.charCodeAt(0).toString(16).padStart(4, "0")}`);
|
|
43459
|
+
var realpathOrNull = (path) => {
|
|
43460
|
+
try {
|
|
43461
|
+
return realpathSync9(path);
|
|
43462
|
+
} catch {
|
|
43463
|
+
return null;
|
|
43464
|
+
}
|
|
43465
|
+
};
|
|
43466
|
+
function discoveryExecutable(agent) {
|
|
43467
|
+
const command = DISCOVERY_RUNTIME_COMMANDS[agent];
|
|
43468
|
+
const found = command ? Bun.which(command) : null;
|
|
43469
|
+
if (!command || !found)
|
|
43470
|
+
return null;
|
|
43471
|
+
const path = resolve19(found), target = realpathOrNull(path);
|
|
43472
|
+
return target === null ? null : { command, path, target };
|
|
43473
|
+
}
|
|
43474
|
+
function recordedDiscoveryExecutable(agent, recorded) {
|
|
43475
|
+
const command = DISCOVERY_RUNTIME_COMMANDS[agent];
|
|
43476
|
+
if (!command || recorded.command !== command)
|
|
43477
|
+
throw new Error(`Recorded ${agent} discovery executable names another command`);
|
|
43478
|
+
const target = realpathOrNull(recorded.path);
|
|
43479
|
+
return target === null ? null : { command, path: recorded.path, target };
|
|
43480
|
+
}
|
|
43481
|
+
var digest2 = (text2) => createHash23("sha256").update(text2).digest("hex");
|
|
43209
43482
|
function parseConfig(text2, path, toml = false) {
|
|
43210
43483
|
try {
|
|
43211
43484
|
const value = toml ? Bun.TOML.parse(text2) : JSON.parse(text2);
|
|
@@ -43217,12 +43490,12 @@ function parseConfig(text2, path, toml = false) {
|
|
|
43217
43490
|
}
|
|
43218
43491
|
}
|
|
43219
43492
|
function safe4(path) {
|
|
43220
|
-
if (!
|
|
43493
|
+
if (!isAbsolute20(path) || path.includes("\x00"))
|
|
43221
43494
|
throw new Error("Expected an absolute native discovery path");
|
|
43222
|
-
for (let cursor = path;; cursor =
|
|
43495
|
+
for (let cursor = path;; cursor = dirname17(cursor)) {
|
|
43223
43496
|
if (lstatSync21(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
|
|
43224
43497
|
throw new Error(`Refusing symlink native discovery input: ${cursor}`);
|
|
43225
|
-
if (
|
|
43498
|
+
if (dirname17(cursor) === cursor)
|
|
43226
43499
|
break;
|
|
43227
43500
|
}
|
|
43228
43501
|
}
|
|
@@ -43241,7 +43514,7 @@ function projectNativeDiscoveryFields(text2, format, fields2, path) {
|
|
|
43241
43514
|
const object6 = format === "yaml" ? parseHermesConfig(text2) : parseConfig(text2, path, format === "toml");
|
|
43242
43515
|
if (!object6 || typeof object6 !== "object" || Array.isArray(object6))
|
|
43243
43516
|
throw new Error("Expected native discovery configuration object");
|
|
43244
|
-
return digest2(JSON.stringify(Object.fromEntries(fields2.map((
|
|
43517
|
+
return digest2(JSON.stringify(Object.fromEntries(fields2.map((field3) => [field3, object6[field3] ?? null]))));
|
|
43245
43518
|
}
|
|
43246
43519
|
function isSupersededSettingsProjection(agent, configPath, source) {
|
|
43247
43520
|
if (agent === "sumi")
|
|
@@ -43286,6 +43559,14 @@ function projected(source, changes, budget2 = discoveryByteBudget()) {
|
|
|
43286
43559
|
throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
|
|
43287
43560
|
return sha2562;
|
|
43288
43561
|
}
|
|
43562
|
+
if (source.hashMode === "claude-marketplace-entry-v1") {
|
|
43563
|
+
if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256) || changes?.has(source.path) || !claudeMarketplaceEntrySourceValid(source))
|
|
43564
|
+
throw new Error("Claude marketplace entry witnesses require an exact reviewed entry without synthetic changes");
|
|
43565
|
+
const sha2562 = captureClaudeMarketplaceEntry(source.path, source.marketplace, source.plugin, budget2).sha256;
|
|
43566
|
+
if (sha2562 !== source.sha256)
|
|
43567
|
+
throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
|
|
43568
|
+
return sha2562;
|
|
43569
|
+
}
|
|
43289
43570
|
if (source.hashMode === "claude-plugin-registry") {
|
|
43290
43571
|
if (source.format !== undefined || source.fields !== undefined || !source.managedPlugins || changes?.has(source.path))
|
|
43291
43572
|
throw new Error("Managed plugin registry witnesses require verified native registrations");
|
|
@@ -43323,7 +43604,7 @@ function absentCodexSkillRoots(binding) {
|
|
|
43323
43604
|
throw new Error("Invalid disabled Codex discovery proof");
|
|
43324
43605
|
if (binding.method !== "reviewed" || controls.every((control) => lstatSync21(control.pluginParent, { throwIfNoEntry: false })))
|
|
43325
43606
|
return [];
|
|
43326
|
-
const cache =
|
|
43607
|
+
const cache = dirname17(dirname17(controls[0].pluginParent)), config = join26(dirname17(dirname17(cache)), "config.toml");
|
|
43327
43608
|
const source = binding.sources.find((source2) => source2.path === config && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined);
|
|
43328
43609
|
if (!source || projected(source) !== source.sha256)
|
|
43329
43610
|
throw new Error("Missing current disabled Codex configuration witness");
|
|
@@ -43331,7 +43612,7 @@ function absentCodexSkillRoots(binding) {
|
|
|
43331
43612
|
return [...new Set(controls.map((control) => control.pluginParent))].filter((parent) => !codexDirectHookSelects(cache, parent) && absentDisabledCodexPluginParent(cache, parent, controls, rules));
|
|
43332
43613
|
}
|
|
43333
43614
|
function codexDirectHookSelects(cache, root2) {
|
|
43334
|
-
const codex =
|
|
43615
|
+
const codex = dirname17(dirname17(cache)), config = Bun.TOML.parse(read2(join26(codex, "config.toml")) ?? "");
|
|
43335
43616
|
const hooks = read2(join26(codex, "hooks.json"));
|
|
43336
43617
|
if (hooks !== null)
|
|
43337
43618
|
hashNativeJsonControls(hooks);
|
|
@@ -43344,7 +43625,7 @@ function retiredCodexRoots(binding) {
|
|
|
43344
43625
|
const controls = binding.codexDisabledPluginSkills;
|
|
43345
43626
|
if (binding.agent !== "codex" || binding.method !== "reviewed" || !Array.isArray(controls) || !controls.length || !Array.isArray(proof.roots) || proof.roots.length > AGENT_POLICY_LIMITS.discoveryRoots || new Set(proof.roots).size !== proof.roots.length || !Array.isArray(proof.directories) || proof.parents !== undefined && (!Array.isArray(proof.parents) || proof.parents.length > AGENT_POLICY_LIMITS.discoveryRoots || new Set(proof.parents).size !== proof.parents.length) || !proof.roots.length && !proof.parents?.length)
|
|
43346
43627
|
throw new Error("Invalid retired Codex materialization proof");
|
|
43347
|
-
const cache =
|
|
43628
|
+
const cache = dirname17(dirname17(controls[0].pluginParent)), config = join26(dirname17(dirname17(cache)), "config.toml");
|
|
43348
43629
|
const source = binding.sources.find((source2) => source2.path === config && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined);
|
|
43349
43630
|
if (!source || projected(source) !== source.sha256)
|
|
43350
43631
|
throw new Error("Missing current retired Codex configuration witness");
|
|
@@ -43361,8 +43642,8 @@ function retiredCodexRoots(binding) {
|
|
|
43361
43642
|
function captureRetiredCodexDiscovery(binding, controls, rules) {
|
|
43362
43643
|
if (binding.agent !== "codex" || binding.method !== "reviewed" || !controls.length)
|
|
43363
43644
|
return binding;
|
|
43364
|
-
const cache =
|
|
43365
|
-
const candidates = binding.sources.filter((source) => source.path.endsWith(sep6 + ".codex-plugin/plugin.json") && source.sha256 !== null && source.format === undefined && source.fields === undefined && [undefined, "bytes"].includes(source.hashMode)).map((source) =>
|
|
43645
|
+
const cache = dirname17(dirname17(controls[0].pluginParent));
|
|
43646
|
+
const candidates = binding.sources.filter((source) => source.path.endsWith(sep6 + ".codex-plugin/plugin.json") && source.sha256 !== null && source.format === undefined && source.fields === undefined && [undefined, "bytes"].includes(source.hashMode)).map((source) => dirname17(dirname17(source.path)));
|
|
43366
43647
|
const roots = [...new Set(candidates)].filter((root2) => !codexDirectHookSelects(cache, root2) && reviewedRetiredCodexRoot(cache, root2, controls, rules, (path) => read2(path), binding.codexRetiredMaterializations?.roots.includes(root2) ?? false)).sort();
|
|
43367
43648
|
const parents3 = reviewedCodexPluginCapabilitiesUnchanged(cache, controls, (path) => read2(path), rules) ? [...new Set(controls.map((control) => control.pluginParent))].filter((parent) => !codexDirectHookSelects(cache, parent) && reviewedDisabledCodexPluginParent(cache, parent, controls, rules)).sort() : [];
|
|
43368
43649
|
const { codexRetiredMaterializations: previous, ...current } = binding;
|
|
@@ -43391,7 +43672,7 @@ function absentRetiredClaudeRoots(binding) {
|
|
|
43391
43672
|
safe4(root2);
|
|
43392
43673
|
if (lstatSync21(root2, { throwIfNoEntry: false }))
|
|
43393
43674
|
continue;
|
|
43394
|
-
const claude =
|
|
43675
|
+
const claude = dirname17(dirname17(cache)), settings = join26(claude, "settings.json"), registry = join26(claude, "plugins/installed_plugins.json");
|
|
43395
43676
|
const full = (path) => binding.sources.find((item) => item.path === path && item.sha256 !== null && item.format === undefined && item.fields === undefined);
|
|
43396
43677
|
const configSource = full(settings), registrySource = full(registry);
|
|
43397
43678
|
if (!configSource || !registrySource || projected(configSource) !== configSource.sha256 || projected(registrySource) !== registrySource.sha256)
|
|
@@ -43408,7 +43689,7 @@ function absentRetiredClaudeRoots(binding) {
|
|
|
43408
43689
|
if (!Array.isArray(rows) || rows.length !== 1 || rows[0]?.scope !== "user" || typeof rows[0]?.installPath !== "string")
|
|
43409
43690
|
continue;
|
|
43410
43691
|
const active = rows[0].installPath;
|
|
43411
|
-
if (rows[0].version !==
|
|
43692
|
+
if (rows[0].version !== basename9(active) || resolve19(active) !== active || dirname17(active) !== dirname17(root2) || active === root2 || !lstatSync21(active, { throwIfNoEntry: false })?.isDirectory() || realpathSync9(active) !== active)
|
|
43412
43693
|
continue;
|
|
43413
43694
|
const activeManifest = full(join26(active, ".claude-plugin/plugin.json"));
|
|
43414
43695
|
if (!activeManifest || projected(activeManifest) !== activeManifest.sha256)
|
|
@@ -43459,7 +43740,7 @@ function verifyAgentDiscovery(binding, codexRecovery) {
|
|
|
43459
43740
|
assertMarketplaceBinding(binding, source);
|
|
43460
43741
|
if (source.hashMode === "claude-plugin-registry" && binding.agent !== "claude")
|
|
43461
43742
|
throw new Error("Managed Claude registry witnesses cannot apply to another agent");
|
|
43462
|
-
if (source.format !== undefined && (!["json", "toml", "yaml"].includes(source.format) || !Array.isArray(source.fields) || !source.fields.length || source.fields.length > 64 || source.fields.some((
|
|
43743
|
+
if (source.format !== undefined && (!["json", "toml", "yaml"].includes(source.format) || !Array.isArray(source.fields) || !source.fields.length || source.fields.length > 64 || source.fields.some((field3) => typeof field3 !== "string" || !field3)))
|
|
43463
43744
|
throw new Error("Invalid native discovery projection");
|
|
43464
43745
|
if (source.sha256 !== null && !/^[a-f0-9]{64}$/.test(source.sha256))
|
|
43465
43746
|
throw new Error("Invalid native discovery digest");
|
|
@@ -43487,15 +43768,15 @@ function codexInstallationRoots(binding) {
|
|
|
43487
43768
|
const proof = binding.codexInstallationInputs;
|
|
43488
43769
|
if (proof === undefined)
|
|
43489
43770
|
return [];
|
|
43490
|
-
if (binding.agent !== "codex" || binding.method !== "reviewed" || proof.version
|
|
43771
|
+
if (binding.agent !== "codex" || binding.method !== "reviewed" || !supportsCodexNativeCapability(proof.version, "installed-plugin-review") || !/^[a-f0-9]{64}$/.test(proof.catalogSha256) || !Array.isArray(proof.plugins) || !proof.plugins.length)
|
|
43491
43772
|
throw new Error("Invalid native installation input proof");
|
|
43492
|
-
const cache =
|
|
43493
|
-
const config = join26(
|
|
43773
|
+
const cache = dirname17(dirname17(proof.plugins[0].pluginParent));
|
|
43774
|
+
const config = join26(dirname17(dirname17(cache)), "config.toml"), home = dirname17(dirname17(dirname17(cache)));
|
|
43494
43775
|
const configSource = binding.sources.find((source) => source.path === config && source.sha256 !== null && (!source.format || source.format === "toml" && source.fields?.includes("plugins")));
|
|
43495
43776
|
const nativeRoots = NATIVE_SKILL_ROOTS.filter(([agent]) => agent === "codex").map(([, path]) => join26(home, path));
|
|
43496
|
-
if (!configSource || proof.plugins.some((input) => nativeRoots.some((root2) => root2 === input.sourceRoot || root2.startsWith(input.sourceRoot + sep6) || input.sourceRoot.startsWith(root2 + sep6)) || binding.sources.some((source) =>
|
|
43777
|
+
if (!configSource || proof.plugins.some((input) => nativeRoots.some((root2) => root2 === input.sourceRoot || root2.startsWith(input.sourceRoot + sep6) || input.sourceRoot.startsWith(root2 + sep6)) || binding.sources.some((source) => basename9(source.path) === "config.toml" && (source.path === input.sourceRoot || source.path.startsWith(input.sourceRoot + sep6)))))
|
|
43497
43778
|
throw new Error("Native installation input overlaps configuration or loading roots");
|
|
43498
|
-
if (proof.plugins.some((input) =>
|
|
43779
|
+
if (proof.plugins.some((input) => dirname17(dirname17(input.pluginParent)) !== cache || !binding.sources.some((source) => source.path === join26(input.sourceRoot, ".codex-plugin/plugin.json") && source.sha256 !== null && source.format === undefined && source.fields === undefined)))
|
|
43499
43780
|
throw new Error("Missing native installation input source witness");
|
|
43500
43781
|
return reviewedCodexPluginSourceRoots(cache, proof.plugins, (path) => {
|
|
43501
43782
|
const text2 = read2(path);
|
|
@@ -43505,16 +43786,18 @@ function codexInstallationRoots(binding) {
|
|
|
43505
43786
|
});
|
|
43506
43787
|
}
|
|
43507
43788
|
function assertMarketplaceBinding(binding, source) {
|
|
43508
|
-
if (source.hashMode === "claude-plugin-manifest-v1" && (binding.agent !== "claude" ||
|
|
43789
|
+
if (source.hashMode === "claude-plugin-manifest-v1" && (binding.agent !== "claude" || basename9(source.path) !== "plugin.json" || !source.path.endsWith(join26(sep6, ".claude-plugin", "plugin.json"))))
|
|
43509
43790
|
throw new Error("Claude plugin manifest witnesses require Claude plugin discovery");
|
|
43510
|
-
if (source.hashMode === "sumi-settings-v1" && (binding.agent !== "sumi" || binding.method !== "reviewed" ||
|
|
43791
|
+
if (source.hashMode === "sumi-settings-v1" && (binding.agent !== "sumi" || binding.method !== "reviewed" || basename9(source.path) !== "sumi.json"))
|
|
43511
43792
|
throw new Error("Sumi settings witnesses require explicit reviewed Sumi configuration");
|
|
43512
|
-
if ((source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")) && (binding.agent !== "codex" || binding.method !== "reviewed" ||
|
|
43793
|
+
if ((source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")) && (binding.agent !== "codex" || binding.method !== "reviewed" || basename9(source.path) !== "config.toml"))
|
|
43513
43794
|
throw new Error("Codex settings witnesses require explicit reviewed Codex configuration");
|
|
43514
|
-
if ((source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4")) && (binding.agent !== "claude" || binding.method !== "reviewed" ||
|
|
43795
|
+
if ((source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4")) && (binding.agent !== "claude" || binding.method !== "reviewed" || basename9(source.path) !== "settings.json"))
|
|
43515
43796
|
throw new Error("Claude settings witnesses require explicit reviewed Claude configuration");
|
|
43516
43797
|
if ((source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2") && (binding.agent !== "claude" || binding.method !== "reviewed"))
|
|
43517
43798
|
throw new Error("Claude marketplace witnesses require explicit reviewed Claude discovery");
|
|
43799
|
+
if (source.hashMode === "claude-marketplace-entry-v1" && (binding.agent !== "claude" || binding.method !== "reviewed" || !claudeMarketplaceEntrySourceValid(source)))
|
|
43800
|
+
throw new Error("Claude marketplace entry witnesses require explicit reviewed Claude discovery of one named entry");
|
|
43518
43801
|
}
|
|
43519
43802
|
function rebindAgentDiscovery(binding, changes) {
|
|
43520
43803
|
const budget2 = discoveryByteBudget();
|
|
@@ -43547,10 +43830,10 @@ function captureDiscoveryPathSources(paths) {
|
|
|
43547
43830
|
const budget2 = discoveryByteBudget();
|
|
43548
43831
|
return paths.map((path) => ({ path, hashMode: "path-bytes", sha256: hashDiscoveryPathFile(path, budget2) }));
|
|
43549
43832
|
}
|
|
43550
|
-
function assertProjectDiscovery(agent, directories, home,
|
|
43551
|
-
const homeConfigPath =
|
|
43833
|
+
function assertProjectDiscovery(agent, directories, home, canonical8 = resolve19, reviewed) {
|
|
43834
|
+
const homeConfigPath = canonical8(agentDiscoveryConfigPath(home, agent));
|
|
43552
43835
|
for (const directory of directories) {
|
|
43553
|
-
const isHome =
|
|
43836
|
+
const isHome = resolve19(directory) === resolve19(home);
|
|
43554
43837
|
if (agent === "hermes") {
|
|
43555
43838
|
assertHermesEnvironment(home);
|
|
43556
43839
|
continue;
|
|
@@ -43559,7 +43842,7 @@ function assertProjectDiscovery(agent, directories, home, canonical7 = resolve17
|
|
|
43559
43842
|
continue;
|
|
43560
43843
|
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"] : agent === "sumi" ? ["sumi.json", "sumi.jsonc", ".sumi/sumi.json", ".sumi/sumi.jsonc"] : [".cursor/hooks.json"];
|
|
43561
43844
|
for (const suffix of paths) {
|
|
43562
|
-
const path =
|
|
43845
|
+
const path = canonical8(join26(directory, suffix)), raw = read2(path);
|
|
43563
43846
|
if (raw === null)
|
|
43564
43847
|
continue;
|
|
43565
43848
|
const isRootAliasedHomeConfig = agent === "claude" && suffix === ".claude/settings.json" || agent === "codex" && suffix === ".codex/config.toml";
|
|
@@ -43575,7 +43858,7 @@ function assertProjectDiscovery(agent, directories, home, canonical7 = resolve17
|
|
|
43575
43858
|
const managed = reviewed.sources.flatMap((source) => source.hashMode === "claude-plugin-registry" ? source.managedPlugins ?? [] : []);
|
|
43576
43859
|
if (exact && projected(exact) === exact.sha256 && managed.length) {
|
|
43577
43860
|
const bindings = managed.map((item) => readPluginBinding(item.storeRoot, item.bindingId));
|
|
43578
|
-
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 ===
|
|
43861
|
+
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 === canonical8(directory))));
|
|
43579
43862
|
}
|
|
43580
43863
|
}
|
|
43581
43864
|
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)))
|
|
@@ -43583,13 +43866,13 @@ function assertProjectDiscovery(agent, directories, home, canonical7 = resolve17
|
|
|
43583
43866
|
}
|
|
43584
43867
|
if (agent === "sumi")
|
|
43585
43868
|
for (const name of ["plugin", "plugins"]) {
|
|
43586
|
-
const path =
|
|
43869
|
+
const path = canonical8(join26(directory, ".sumi", name));
|
|
43587
43870
|
safe4(path);
|
|
43588
43871
|
if (lstatSync21(path, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(path).length)
|
|
43589
43872
|
throw new Error(`NATIVE_SKILL_DRIFT: project Sumi plugins require a dedicated discovery review: ${path}`);
|
|
43590
43873
|
}
|
|
43591
43874
|
if (agent === "claude") {
|
|
43592
|
-
const commands =
|
|
43875
|
+
const commands = canonical8(join26(directory, ".claude/commands"));
|
|
43593
43876
|
safe4(commands);
|
|
43594
43877
|
if (lstatSync21(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length)
|
|
43595
43878
|
throw new Error("NATIVE_SKILL_DRIFT: legacy project command discovery requires a dedicated format adapter");
|
|
@@ -43601,11 +43884,37 @@ function agentDiscoveryConfigPath(home, agent) {
|
|
|
43601
43884
|
return sumiConfigPath(home);
|
|
43602
43885
|
return join26(home, agent === "hermes" ? ".hermes/config.yaml" : agent === "opencode" ? ".config/opencode/opencode.json" : `.${agent}/${agent === "codex" ? "config.toml" : agent === "cursor" ? "hooks.json" : "settings.json"}`);
|
|
43603
43886
|
}
|
|
43887
|
+
function verifyAutomaticDiscoveryClosure(binding, options) {
|
|
43888
|
+
const command = DISCOVERY_RUNTIME_COMMANDS[binding.agent], recorded = options.executable;
|
|
43889
|
+
const onPath = discoveryExecutable(binding.agent);
|
|
43890
|
+
let runtime, gap;
|
|
43891
|
+
if (recorded) {
|
|
43892
|
+
runtime = recordedDiscoveryExecutable(binding.agent, recorded);
|
|
43893
|
+
if (runtime && runtime.target !== recorded.target)
|
|
43894
|
+
throw new Error(`${options.change}: the recorded ${binding.agent} executable now resolves to ${quotedPath(runtime.target)}, not the reviewed ${quotedPath(recorded.target)}`);
|
|
43895
|
+
if (onPath && onPath.target !== recorded.target)
|
|
43896
|
+
throw new Error(`${options.change}: the "${command}" on this process's PATH resolves to ${quotedPath(onPath.target)}, not the reviewed ${quotedPath(recorded.target)}`);
|
|
43897
|
+
if (!runtime)
|
|
43898
|
+
gap = `the recorded executable ${quotedPath(recorded.path)} no longer resolves. Restore it, or review the change with skills hook install`;
|
|
43899
|
+
} else {
|
|
43900
|
+
runtime = onPath;
|
|
43901
|
+
if (!runtime)
|
|
43902
|
+
gap = "it is not on this process's PATH, and the reviewed policy has no recorded executable path. Run with the PATH used for the review, or run skills hook install there to record it";
|
|
43903
|
+
}
|
|
43904
|
+
const current = resolveAgentDiscovery({ home: options.home, agent: binding.agent, canonical: options.canonical, executable: runtime });
|
|
43905
|
+
if (JSON.stringify(current) === JSON.stringify(binding))
|
|
43906
|
+
return;
|
|
43907
|
+
const reviewedWithRuntime = (binding.builtinNames?.length ?? 0) > 0 || binding.sources.some((source) => basename9(source.path) === "package.json");
|
|
43908
|
+
const otherwiseCurrent = current.method === binding.method && JSON.stringify(current.roots) === JSON.stringify(binding.roots) && JSON.stringify(current.directories) === JSON.stringify(binding.directories) && current.sources.every((source) => binding.sources.some((saved) => isDeepStrictEqual6(saved, source)));
|
|
43909
|
+
if (command && gap && runtime === null && reviewedWithRuntime && otherwiseCurrent)
|
|
43910
|
+
throw discoveryRootUnresolved(binding.agent, command, gap);
|
|
43911
|
+
throw new Error(options.change);
|
|
43912
|
+
}
|
|
43604
43913
|
function resolveAgentDiscovery(options) {
|
|
43605
|
-
const
|
|
43914
|
+
const canonical8 = options.canonical ?? resolve19, home = resolve19(options.home), agent = options.agent;
|
|
43606
43915
|
const sources = [], roots = new Set, builtinNames = [];
|
|
43607
43916
|
const witness = (path, format, fields2, hashMode) => {
|
|
43608
|
-
const source = { path:
|
|
43917
|
+
const source = { path: canonical8(path), sha256: null, ...format ? { format, fields: fields2 } : {}, ...hashMode ? { hashMode } : {} };
|
|
43609
43918
|
source.sha256 = projected(source);
|
|
43610
43919
|
sources.push(source);
|
|
43611
43920
|
return read2(source.path);
|
|
@@ -43627,13 +43936,13 @@ function resolveAgentDiscovery(options) {
|
|
|
43627
43936
|
unresolved("JSONC configuration requires a supported format adapter");
|
|
43628
43937
|
for (const root2 of [directory, join26(home, ".claude"), join26(home, ".agents")])
|
|
43629
43938
|
for (const name of ["skill", "skills"])
|
|
43630
|
-
roots.add(
|
|
43939
|
+
roots.add(canonical8(join26(root2, name)));
|
|
43631
43940
|
if (config.skills !== undefined && (!Array.isArray(config.skills) || config.skills.some((path) => typeof path !== "string")))
|
|
43632
43941
|
unresolved("skills must be a string array");
|
|
43633
43942
|
for (const value of config.skills ?? []) {
|
|
43634
|
-
if (typeof value !== "string" || /[\0$]/.test(value) || !value || !(
|
|
43943
|
+
if (typeof value !== "string" || /[\0$]/.test(value) || !value || !(isAbsolute20(value) || value.startsWith("~/")))
|
|
43635
43944
|
unresolved("remote or relative skill sources need a dedicated discovery adapter");
|
|
43636
|
-
roots.add(
|
|
43945
|
+
roots.add(canonical8(value.startsWith("~/") ? join26(home, value.slice(2)) : value));
|
|
43637
43946
|
}
|
|
43638
43947
|
for (const key of ["plugin", "plugins"])
|
|
43639
43948
|
if (config[key] !== undefined && !Array.isArray(config[key]))
|
|
@@ -43672,23 +43981,23 @@ function resolveAgentDiscovery(options) {
|
|
|
43672
43981
|
continue;
|
|
43673
43982
|
if (normalized.startsWith("~") && normalized !== "~" && !normalized.startsWith("~/"))
|
|
43674
43983
|
unresolved("user-specific tilde expansion requires a separate discovery adapter");
|
|
43675
|
-
const path = normalized === "~" ? home : normalized.startsWith("~/") ? join26(home, normalized.slice(2)) :
|
|
43984
|
+
const path = normalized === "~" ? home : normalized.startsWith("~/") ? join26(home, normalized.slice(2)) : resolve19(home, ".hermes", normalized);
|
|
43676
43985
|
safe4(path);
|
|
43677
43986
|
roots.add(path);
|
|
43678
43987
|
}
|
|
43679
43988
|
}
|
|
43680
43989
|
if (agent === "gemini") {
|
|
43681
|
-
const executable2 =
|
|
43990
|
+
const executable2 = options.executable === undefined ? discoveryExecutable(agent) : options.executable;
|
|
43682
43991
|
if (executable2) {
|
|
43683
43992
|
let packageRoot;
|
|
43684
|
-
for (let directory =
|
|
43993
|
+
for (let directory = dirname17(executable2.target), depth = 0;depth < 8; directory = dirname17(directory), depth++) {
|
|
43685
43994
|
const path = join26(directory, "package.json"), raw = read2(path);
|
|
43686
43995
|
if (raw !== null && parseConfig(raw, path).name === "@google/gemini-cli") {
|
|
43687
43996
|
packageRoot = directory;
|
|
43688
43997
|
witness(path);
|
|
43689
43998
|
break;
|
|
43690
43999
|
}
|
|
43691
|
-
if (
|
|
44000
|
+
if (dirname17(directory) === directory)
|
|
43692
44001
|
break;
|
|
43693
44002
|
}
|
|
43694
44003
|
if (!packageRoot)
|
|
@@ -43711,11 +44020,11 @@ function resolveAgentDiscovery(options) {
|
|
|
43711
44020
|
if (retained.agent !== agent || retained.method !== "reviewed")
|
|
43712
44021
|
unresolved("invalid retained review");
|
|
43713
44022
|
verifyAgentDiscovery(retained);
|
|
43714
|
-
if (!retained.sources.some((source) => source.path ===
|
|
44023
|
+
if (!retained.sources.some((source) => source.path === canonical8(configPath) && source.format === undefined && source.fields === undefined))
|
|
43715
44024
|
unresolved("retained review is missing the full agent configuration source");
|
|
43716
|
-
if (retained.sources.some((source) => (source.hashMode === "sumi-settings-v1" || source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !==
|
|
44025
|
+
if (retained.sources.some((source) => (source.hashMode === "sumi-settings-v1" || source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !== canonical8(configPath)))
|
|
43717
44026
|
unresolved("retained settings witness names another configuration source");
|
|
43718
|
-
const covered = supersedesSettingsProjection(agent, retained.sources,
|
|
44027
|
+
const covered = supersedesSettingsProjection(agent, retained.sources, canonical8(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical8(configPath), source)) : sources;
|
|
43719
44028
|
if (covered.some((source) => !retained.sources.some((saved) => isDeepStrictEqual6(saved, source))) || [...roots].some((root2) => !retained.roots.includes(root2)) || agent === "gemini" && JSON.stringify(retained.builtinNames) !== JSON.stringify(builtinNames))
|
|
43720
44029
|
unresolved("retained review is missing current runtime discovery coverage");
|
|
43721
44030
|
return retained;
|
|
@@ -43727,15 +44036,15 @@ function resolveAgentDiscovery(options) {
|
|
|
43727
44036
|
if (review.sources.some((source) => source.format !== undefined || source.fields !== undefined))
|
|
43728
44037
|
throw new Error("Explicit discovery reviews require full source-file hashes");
|
|
43729
44038
|
verifyAgentDiscovery(supplied);
|
|
43730
|
-
if (review.sources.some((source) => (source.hashMode === "sumi-settings-v1" || source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !==
|
|
44039
|
+
if (review.sources.some((source) => (source.hashMode === "sumi-settings-v1" || source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !== canonical8(configPath)))
|
|
43731
44040
|
throw new Error("Semantic settings witnesses must name the configured agent configuration source");
|
|
43732
|
-
if (!review.sources.some((source) => source.path ===
|
|
44041
|
+
if (!review.sources.some((source) => source.path === canonical8(configPath)))
|
|
43733
44042
|
throw new Error("Discovery review must include the agent configuration source");
|
|
43734
|
-
const reviewedSources = supersedesSettingsProjection(agent, review.sources,
|
|
44043
|
+
const reviewedSources = supersedesSettingsProjection(agent, review.sources, canonical8(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical8(configPath), source)) : sources;
|
|
43735
44044
|
const reviewedSourcesWithManifestProjection = review.sources.map((source) => {
|
|
43736
|
-
if (agent !== "claude" || source.sha256 === null || source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || source.hashMode !== undefined && source.hashMode !== "bytes" ||
|
|
44045
|
+
if (agent !== "claude" || source.sha256 === null || source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || source.hashMode !== undefined && source.hashMode !== "bytes" || basename9(source.path) !== "plugin.json" || !source.path.endsWith(join26(sep6, ".claude-plugin", "plugin.json")))
|
|
43737
44046
|
return source;
|
|
43738
|
-
const pluginRoot =
|
|
44047
|
+
const pluginRoot = dirname17(dirname17(source.path)), hooksPath = join26(pluginRoot, "hooks/hooks.json");
|
|
43739
44048
|
const hookStat = lstatSync21(hooksPath, { throwIfNoEntry: false });
|
|
43740
44049
|
const text2 = read2(source.path);
|
|
43741
44050
|
if (text2 === null)
|
|
@@ -43750,13 +44059,13 @@ function resolveAgentDiscovery(options) {
|
|
|
43750
44059
|
if (manifest.hooks !== undefined) {
|
|
43751
44060
|
if (typeof manifest.hooks !== "string")
|
|
43752
44061
|
throw new Error("Reviewed Claude plugin manifest has an unsupported hooks target");
|
|
43753
|
-
const declaredHookPath =
|
|
44062
|
+
const declaredHookPath = resolve19(pluginRoot, manifest.hooks);
|
|
43754
44063
|
if (!declaredHookPath.startsWith(pluginRoot + sep6))
|
|
43755
44064
|
throw new Error("Reviewed Claude plugin hooks target escapes its root");
|
|
43756
44065
|
reviewedHookPaths.add(declaredHookPath);
|
|
43757
44066
|
}
|
|
43758
44067
|
for (const hooksFile of reviewedHookPaths)
|
|
43759
|
-
if (!review.sources.some((hook) => hook.path ===
|
|
44068
|
+
if (!review.sources.some((hook) => hook.path === canonical8(hooksFile) && hook.sha256 !== null && hook.format === undefined && hook.fields === undefined && hook.managedPlugins === undefined && (hook.hashMode === undefined || hook.hashMode === "bytes")))
|
|
43760
44069
|
throw new Error("Reviewed Claude plugin manifest requires separately reviewed exact hook file sources");
|
|
43761
44070
|
return { path: source.path, sha256: manifestSha256, hashMode: "claude-plugin-manifest-v1" };
|
|
43762
44071
|
});
|
|
@@ -43765,7 +44074,7 @@ function resolveAgentDiscovery(options) {
|
|
|
43765
44074
|
return { ...supplied, roots: [...new Set([...roots, ...supplied.roots])].sort(), sources: unique, ...agent === "gemini" ? { builtinNames } : {} };
|
|
43766
44075
|
}
|
|
43767
44076
|
function plugin(root2) {
|
|
43768
|
-
root2 =
|
|
44077
|
+
root2 = canonical8(root2);
|
|
43769
44078
|
safe4(root2);
|
|
43770
44079
|
const manifestPath = join26(root2, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
|
|
43771
44080
|
const raw = witness(manifestPath, undefined, undefined, agent === "claude" ? "claude-plugin-manifest-v1" : undefined);
|
|
@@ -43788,16 +44097,16 @@ function resolveAgentDiscovery(options) {
|
|
|
43788
44097
|
if (agent === "claude")
|
|
43789
44098
|
roots.add(join26(root2, "skills"));
|
|
43790
44099
|
for (const value of declared) {
|
|
43791
|
-
const path =
|
|
44100
|
+
const path = resolve19(root2, value);
|
|
43792
44101
|
if (path !== root2 && !path.startsWith(root2 + sep6))
|
|
43793
44102
|
unresolved("plugin skill path escapes its root");
|
|
43794
|
-
roots.add(path.endsWith(`${sep6}SKILL.md`) ?
|
|
44103
|
+
roots.add(path.endsWith(`${sep6}SKILL.md`) ? dirname17(path) : path);
|
|
43795
44104
|
}
|
|
43796
44105
|
}
|
|
43797
44106
|
if (agent === "claude") {
|
|
43798
44107
|
const registrations = witness(join26(home, ".claude/plugins/installed_plugins.json"));
|
|
43799
44108
|
const installed = registrations === null ? {} : parseConfig(registrations, join26(home, ".claude/plugins/installed_plugins.json")).plugins;
|
|
43800
|
-
const commands =
|
|
44109
|
+
const commands = canonical8(join26(home, ".claude/commands"));
|
|
43801
44110
|
safe4(commands);
|
|
43802
44111
|
if (lstatSync21(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length)
|
|
43803
44112
|
unresolved("legacy home command discovery requires a dedicated format adapter");
|
|
@@ -43819,7 +44128,7 @@ function resolveAgentDiscovery(options) {
|
|
|
43819
44128
|
unresolved("unsupported plugin enablement");
|
|
43820
44129
|
const split = id2.lastIndexOf("@"), name = id2.slice(0, split), marketplace = id2.slice(split + 1);
|
|
43821
44130
|
const market = config.marketplaces?.[marketplace] ?? (marketplace === "personal" ? { source_type: "local", source: home } : undefined);
|
|
43822
|
-
if (split < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !
|
|
44131
|
+
if (split < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !isAbsolute20(market.source))
|
|
43823
44132
|
unresolved("enabled plugin marketplace is not an explicit local source");
|
|
43824
44133
|
const catalogText = witness(join26(market.source, ".agents/plugins/marketplace.json"));
|
|
43825
44134
|
if (catalogText === null)
|
|
@@ -43827,7 +44136,7 @@ function resolveAgentDiscovery(options) {
|
|
|
43827
44136
|
const catalog = parseConfig(catalogText, join26(market.source, ".agents/plugins/marketplace.json")), matches = Array.isArray(catalog.plugins) ? catalog.plugins.filter((item) => item.name === name) : [];
|
|
43828
44137
|
if (matches.length !== 1 || matches[0]?.source?.source !== "local" || typeof matches[0]?.source?.path !== "string")
|
|
43829
44138
|
unresolved("plugin catalog source is missing or ambiguous");
|
|
43830
|
-
plugin(
|
|
44139
|
+
plugin(resolve19(market.source, matches[0].source.path));
|
|
43831
44140
|
}
|
|
43832
44141
|
} else if (agent === "opencode") {
|
|
43833
44142
|
if (witness(join26(home, ".config/opencode/opencode.jsonc")) !== null || witness(join26(home, ".config/opencode/config.json")) !== null)
|
|
@@ -43835,7 +44144,7 @@ function resolveAgentDiscovery(options) {
|
|
|
43835
44144
|
if ((config.plugin?.length ?? 0) > 0 || config.skills?.urls?.length)
|
|
43836
44145
|
unresolved("external plugin or remote skill source");
|
|
43837
44146
|
for (const path of config.skills?.paths ?? []) {
|
|
43838
|
-
if (typeof path !== "string" || !
|
|
44147
|
+
if (typeof path !== "string" || !isAbsolute20(path))
|
|
43839
44148
|
unresolved("relative or malformed added skill root");
|
|
43840
44149
|
roots.add(path);
|
|
43841
44150
|
}
|
|
@@ -43844,7 +44153,7 @@ function resolveAgentDiscovery(options) {
|
|
|
43844
44153
|
if (lstatSync21(localPlugins, { throwIfNoEntry: false }) && readdirSync7(localPlugins).some((name) => name !== "skills-cli.js"))
|
|
43845
44154
|
unresolved("additional local plugin hooks require review");
|
|
43846
44155
|
} else if (agent === "sumi") {
|
|
43847
|
-
if ((config.plugin?.length ?? 0) > 0 || (config.plugins?.length ?? 0) > 0 || sources.some((source) => source.path !==
|
|
44156
|
+
if ((config.plugin?.length ?? 0) > 0 || (config.plugins?.length ?? 0) > 0 || sources.some((source) => source.path !== canonical8(configPath) && source.path !== canonical8(join26(sumiConfigDirectory(home), "sumi.jsonc")) && source.sha256 !== null))
|
|
43848
44157
|
unresolved("external or foreign local plugins require review");
|
|
43849
44158
|
} else if (agent === "hermes") {
|
|
43850
44159
|
for (const directory of [join26(home, ".hermes/plugins"), join26(home, ".hermes/hermes-agent")]) {
|
|
@@ -43874,7 +44183,7 @@ function resolveAgentDiscovery(options) {
|
|
|
43874
44183
|
roots.add(join26(root2, "skills"));
|
|
43875
44184
|
}
|
|
43876
44185
|
}
|
|
43877
|
-
return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join26(home, ".hermes/plugins"), join26(home, ".hermes/hermes-agent")].map((path) =>
|
|
44186
|
+
return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join26(home, ".hermes/plugins"), join26(home, ".hermes/hermes-agent")].map((path) => canonical8(path))) } : {} };
|
|
43878
44187
|
}
|
|
43879
44188
|
|
|
43880
44189
|
// src/lib/agent-adapters.ts
|
|
@@ -43950,29 +44259,29 @@ var CODEX_SKILL_CONFIG_SECTIONS = /^\[\[skills\.config\]\][^\n]*(?:\n(?!\s*\[)[^
|
|
|
43950
44259
|
var codexPathConfigRefusal = () => new Error("Codex skill path controls require ordinary [[skills.config]] TOML tables or a native single-line inline array; preserve and review unsupported inline, dotted, or malformed definitions before running skills hook install");
|
|
43951
44260
|
function splitTopLevel(value, delimiter2) {
|
|
43952
44261
|
const result = [];
|
|
43953
|
-
let start = 0, square = 0, curly = 0,
|
|
44262
|
+
let start = 0, square = 0, curly = 0, quote3 = null, escaped = false;
|
|
43954
44263
|
for (let index = 0;index < value.length; index++) {
|
|
43955
44264
|
const char = value[index];
|
|
43956
|
-
if (
|
|
44265
|
+
if (quote3 === "double") {
|
|
43957
44266
|
if (escaped)
|
|
43958
44267
|
escaped = false;
|
|
43959
44268
|
else if (char === "\\")
|
|
43960
44269
|
escaped = true;
|
|
43961
44270
|
else if (char === '"')
|
|
43962
|
-
|
|
44271
|
+
quote3 = null;
|
|
43963
44272
|
continue;
|
|
43964
44273
|
}
|
|
43965
|
-
if (
|
|
44274
|
+
if (quote3 === "literal") {
|
|
43966
44275
|
if (char === "'")
|
|
43967
|
-
|
|
44276
|
+
quote3 = null;
|
|
43968
44277
|
continue;
|
|
43969
44278
|
}
|
|
43970
44279
|
if (char === '"') {
|
|
43971
|
-
|
|
44280
|
+
quote3 = "double";
|
|
43972
44281
|
continue;
|
|
43973
44282
|
}
|
|
43974
44283
|
if (char === "'") {
|
|
43975
|
-
|
|
44284
|
+
quote3 = "literal";
|
|
43976
44285
|
continue;
|
|
43977
44286
|
}
|
|
43978
44287
|
if (char === "[")
|
|
@@ -43990,7 +44299,7 @@ function splitTopLevel(value, delimiter2) {
|
|
|
43990
44299
|
start = index + 1;
|
|
43991
44300
|
}
|
|
43992
44301
|
}
|
|
43993
|
-
if (
|
|
44302
|
+
if (quote3 !== null || square !== 0 || curly !== 0)
|
|
43994
44303
|
return null;
|
|
43995
44304
|
result.push(value.slice(start));
|
|
43996
44305
|
return result;
|
|
@@ -43998,29 +44307,29 @@ function splitTopLevel(value, delimiter2) {
|
|
|
43998
44307
|
function inlineArrayEnd(value) {
|
|
43999
44308
|
if (!value.startsWith("["))
|
|
44000
44309
|
return null;
|
|
44001
|
-
let square = 0, curly = 0,
|
|
44310
|
+
let square = 0, curly = 0, quote3 = null, escaped = false;
|
|
44002
44311
|
for (let index = 0;index < value.length; index++) {
|
|
44003
44312
|
const char = value[index];
|
|
44004
|
-
if (
|
|
44313
|
+
if (quote3 === "double") {
|
|
44005
44314
|
if (escaped)
|
|
44006
44315
|
escaped = false;
|
|
44007
44316
|
else if (char === "\\")
|
|
44008
44317
|
escaped = true;
|
|
44009
44318
|
else if (char === '"')
|
|
44010
|
-
|
|
44319
|
+
quote3 = null;
|
|
44011
44320
|
continue;
|
|
44012
44321
|
}
|
|
44013
|
-
if (
|
|
44322
|
+
if (quote3 === "literal") {
|
|
44014
44323
|
if (char === "'")
|
|
44015
|
-
|
|
44324
|
+
quote3 = null;
|
|
44016
44325
|
continue;
|
|
44017
44326
|
}
|
|
44018
44327
|
if (char === '"') {
|
|
44019
|
-
|
|
44328
|
+
quote3 = "double";
|
|
44020
44329
|
continue;
|
|
44021
44330
|
}
|
|
44022
44331
|
if (char === "'") {
|
|
44023
|
-
|
|
44332
|
+
quote3 = "literal";
|
|
44024
44333
|
continue;
|
|
44025
44334
|
}
|
|
44026
44335
|
if (char === "[")
|
|
@@ -44057,7 +44366,7 @@ function inlineRowsAsTables(value, newline) {
|
|
|
44057
44366
|
const fields2 = splitTopLevel(row.slice(1, -1), ",");
|
|
44058
44367
|
if (!fields2)
|
|
44059
44368
|
return null;
|
|
44060
|
-
const lines = fields2.map((
|
|
44369
|
+
const lines = fields2.map((field3) => field3.trim()).filter(Boolean);
|
|
44061
44370
|
if (lines.some((line) => !/^(?:path|name|enabled)\s*=/.test(line)))
|
|
44062
44371
|
return null;
|
|
44063
44372
|
const keys2 = lines.map((line) => line.slice(0, line.indexOf("=")).trim());
|
|
@@ -44082,27 +44391,27 @@ function normalizeCodexInlinePathConfig(text2) {
|
|
|
44082
44391
|
const matches = [];
|
|
44083
44392
|
for (const assignment of text2.matchAll(/^([ \t]*config[ \t]*=[ \t]*)(.*?)(\r?)$/gm)) {
|
|
44084
44393
|
const rawValue = assignment[2].trimEnd();
|
|
44085
|
-
let
|
|
44394
|
+
let quote3 = null, escaped = false, comment = "";
|
|
44086
44395
|
for (let index = 0;index < rawValue.length; index++) {
|
|
44087
44396
|
const char = rawValue[index];
|
|
44088
|
-
if (
|
|
44397
|
+
if (quote3 === "double") {
|
|
44089
44398
|
if (escaped)
|
|
44090
44399
|
escaped = false;
|
|
44091
44400
|
else if (char === "\\")
|
|
44092
44401
|
escaped = true;
|
|
44093
44402
|
else if (char === '"')
|
|
44094
|
-
|
|
44403
|
+
quote3 = null;
|
|
44095
44404
|
continue;
|
|
44096
44405
|
}
|
|
44097
|
-
if (
|
|
44406
|
+
if (quote3 === "literal") {
|
|
44098
44407
|
if (char === "'")
|
|
44099
|
-
|
|
44408
|
+
quote3 = null;
|
|
44100
44409
|
continue;
|
|
44101
44410
|
}
|
|
44102
44411
|
if (char === '"')
|
|
44103
|
-
|
|
44412
|
+
quote3 = "double";
|
|
44104
44413
|
else if (char === "'")
|
|
44105
|
-
|
|
44414
|
+
quote3 = "literal";
|
|
44106
44415
|
else if (char === "#") {
|
|
44107
44416
|
comment = rawValue.slice(index);
|
|
44108
44417
|
break;
|
|
@@ -44213,9 +44522,9 @@ function disableCodexBundledSkills(text2) {
|
|
|
44213
44522
|
}
|
|
44214
44523
|
|
|
44215
44524
|
// src/cli/commands/runtime-launcher.ts
|
|
44216
|
-
import { createHash as
|
|
44217
|
-
import { closeSync as closeSync17, constants as constants14, fchmodSync as fchmodSync2, fstatSync as fstatSync17, fsyncSync as fsyncSync5, lstatSync as lstatSync22, openSync as openSync17, readFileSync as readFileSync16, readlinkSync as
|
|
44218
|
-
import { isAbsolute as
|
|
44525
|
+
import { createHash as createHash24 } from "crypto";
|
|
44526
|
+
import { closeSync as closeSync17, constants as constants14, fchmodSync as fchmodSync2, fstatSync as fstatSync17, fsyncSync as fsyncSync5, lstatSync as lstatSync22, openSync as openSync17, readFileSync as readFileSync16, readlinkSync as readlinkSync6, realpathSync as realpathSync10, symlinkSync, writeSync as writeSync3 } from "fs";
|
|
44527
|
+
import { isAbsolute as isAbsolute21 } from "path";
|
|
44219
44528
|
var PINNED_LAUNCHER_SCHEMA = "hasna-skills-pinned-launcher-v1";
|
|
44220
44529
|
var LAUNCH_CWD_VARIABLE = "HASNA_SKILLS_LAUNCH_CWD";
|
|
44221
44530
|
var PINNED_LAUNCHER_BUN_FLAGS = ["--config=/dev/null", "--no-env-file", "--no-macros", "--no-install"];
|
|
@@ -44256,10 +44565,10 @@ var PINNED_LAUNCHER_ENV_PREFIXES = ["HASNA", "SKILLS", "SKILL", "MCP", "XDG", "L
|
|
|
44256
44565
|
var ENV_PREFIX = new RegExp(`^(${PINNED_LAUNCHER_ENV_PREFIXES.join("|")})_`);
|
|
44257
44566
|
var ENV_EXACT = new Set(PINNED_LAUNCHER_ENV_NAMES);
|
|
44258
44567
|
function sha2562(bytes) {
|
|
44259
|
-
return
|
|
44568
|
+
return createHash24("sha256").update(bytes).digest("hex");
|
|
44260
44569
|
}
|
|
44261
44570
|
function assertLauncherPath(value, code) {
|
|
44262
|
-
if (typeof value !== "string" || !
|
|
44571
|
+
if (typeof value !== "string" || !isAbsolute21(value) || /['\x00-\x1f\x7f]/.test(value))
|
|
44263
44572
|
throw new Error(code);
|
|
44264
44573
|
}
|
|
44265
44574
|
function renderPinnedLauncher(binding) {
|
|
@@ -44349,7 +44658,7 @@ function assertPinnedLauncherRuntimeSafe(runtime) {
|
|
|
44349
44658
|
}
|
|
44350
44659
|
|
|
44351
44660
|
// src/lib/agent-integration.ts
|
|
44352
|
-
var sha4 = (data) =>
|
|
44661
|
+
var sha4 = (data) => createHash25("sha256").update(data).digest("hex");
|
|
44353
44662
|
var ROOTS = NATIVE_SKILL_ROOTS;
|
|
44354
44663
|
function hasTrustedDarwinAcl(fd, allowDenyOnly = false) {
|
|
44355
44664
|
try {
|
|
@@ -44399,9 +44708,10 @@ function isSystemRootAlias(path) {
|
|
|
44399
44708
|
return false;
|
|
44400
44709
|
const target = `/private${path}`, link = `private${path}`;
|
|
44401
44710
|
const identity5 = (stat2) => `${stat2.dev}:${stat2.ino}:${stat2.ctimeNs}:${stat2.uid}:${stat2.mode}`;
|
|
44711
|
+
const directoryIdentity = (stat2) => `${stat2.dev}:${stat2.ino}:${stat2.uid}:${stat2.mode}`;
|
|
44402
44712
|
try {
|
|
44403
44713
|
const before = lstatSync23(path, { bigint: true });
|
|
44404
|
-
if (!before.isSymbolicLink() || before.uid !== 0n ||
|
|
44714
|
+
if (!before.isSymbolicLink() || before.uid !== 0n || readlinkSync7(path) !== link)
|
|
44405
44715
|
return false;
|
|
44406
44716
|
const directories = ["/", "/private", target].map((directory) => {
|
|
44407
44717
|
const stat2 = lstatSync23(directory, { bigint: true });
|
|
@@ -44414,20 +44724,20 @@ function isSystemRootAlias(path) {
|
|
|
44414
44724
|
throw new Error("Unprotected system temporary directory");
|
|
44415
44725
|
const fd = openSync18(directory, constants15.O_RDONLY | constants15.O_DIRECTORY | constants15.O_NOFOLLOW);
|
|
44416
44726
|
try {
|
|
44417
|
-
if (
|
|
44727
|
+
if (directoryIdentity(fstatSync18(fd, { bigint: true })) !== directoryIdentity(stat2) || !hasTrustedDarwinAcl(fd) || directoryIdentity(fstatSync18(fd, { bigint: true })) !== directoryIdentity(stat2))
|
|
44418
44728
|
throw new Error("Unverified system alias directory ACL");
|
|
44419
44729
|
} finally {
|
|
44420
44730
|
closeSync18(fd);
|
|
44421
44731
|
}
|
|
44422
|
-
return { directory, identity:
|
|
44732
|
+
return { directory, identity: directoryIdentity(stat2) };
|
|
44423
44733
|
});
|
|
44424
|
-
return realpathSync11(path) === target &&
|
|
44734
|
+
return realpathSync11(path) === target && readlinkSync7(path) === link && identity5(lstatSync23(path, { bigint: true })) === identity5(before) && directories.every((item) => directoryIdentity(lstatSync23(item.directory, { bigint: true })) === item.identity);
|
|
44425
44735
|
} catch {
|
|
44426
44736
|
return false;
|
|
44427
44737
|
}
|
|
44428
44738
|
}
|
|
44429
44739
|
function canonicalSystemPath(path) {
|
|
44430
|
-
const absolute =
|
|
44740
|
+
const absolute = resolve20(path), root2 = `/${absolute.split(sep7)[1]}`;
|
|
44431
44741
|
if (process.platform !== "darwin" || !["/var", "/tmp", "/etc"].includes(root2) || !lstatSync23(root2, { throwIfNoEntry: false })?.isSymbolicLink())
|
|
44432
44742
|
return absolute;
|
|
44433
44743
|
if (!isSystemRootAlias(root2))
|
|
@@ -44435,11 +44745,11 @@ function canonicalSystemPath(path) {
|
|
|
44435
44745
|
return `/private${absolute}`;
|
|
44436
44746
|
}
|
|
44437
44747
|
function assertSafePath(path) {
|
|
44438
|
-
let cursor =
|
|
44748
|
+
let cursor = resolve20(path);
|
|
44439
44749
|
while (true) {
|
|
44440
44750
|
if (lstatSync23(cursor, { throwIfNoEntry: false })?.isSymbolicLink() && !isSystemRootAlias(cursor))
|
|
44441
44751
|
throw new Error(`Refusing symlink path: ${cursor}`);
|
|
44442
|
-
const parent =
|
|
44752
|
+
const parent = dirname18(cursor);
|
|
44443
44753
|
if (parent === cursor)
|
|
44444
44754
|
return;
|
|
44445
44755
|
cursor = parent;
|
|
@@ -44451,13 +44761,13 @@ function readRootAlias(home, agent) {
|
|
|
44451
44761
|
const stat2 = lstatSync23(alias, { throwIfNoEntry: false, bigint: true });
|
|
44452
44762
|
if (!stat2?.isSymbolicLink())
|
|
44453
44763
|
throw new Error(`Agent root alias changed after planning: ${alias}`);
|
|
44454
|
-
const link =
|
|
44764
|
+
const link = readlinkSync7(alias), targetPath = resolve20(dirname18(alias), link);
|
|
44455
44765
|
assertSafePath(targetPath);
|
|
44456
44766
|
const targetStat = lstatSync23(targetPath, { throwIfNoEntry: false });
|
|
44457
44767
|
if (!targetStat?.isDirectory())
|
|
44458
44768
|
throw new Error(`Agent root alias must target an existing directory: ${alias}`);
|
|
44459
44769
|
const target = realpathSync11(targetPath), inside = relative5(realHome, target);
|
|
44460
|
-
if (!inside || inside === ".." || inside.startsWith(`..${sep7}`) ||
|
|
44770
|
+
if (!inside || inside === ".." || inside.startsWith(`..${sep7}`) || isAbsolute22(inside))
|
|
44461
44771
|
throw new Error(`Agent root alias target must be inside the real home: ${alias}`);
|
|
44462
44772
|
return { agent, home: realHome, alias, target, link, aliasIdentity: `${stat2.dev}:${stat2.ino}:${stat2.ctimeNs}`, targetIdentity: `${targetStat.dev}:${targetStat.ino}` };
|
|
44463
44773
|
}
|
|
@@ -44483,13 +44793,13 @@ function disabledCodexSkillPaths(config, aliases) {
|
|
|
44483
44793
|
const rows = skills.config;
|
|
44484
44794
|
if (!Array.isArray(rows))
|
|
44485
44795
|
return [];
|
|
44486
|
-
if (rows.some((entry) => !entry || typeof entry !== "object" || Array.isArray(entry) || typeof entry.enabled !== "boolean" || entry.path !== undefined === (entry.name !== undefined) || entry.path !== undefined && (typeof entry.path !== "string" || !
|
|
44796
|
+
if (rows.some((entry) => !entry || typeof entry !== "object" || Array.isArray(entry) || typeof entry.enabled !== "boolean" || entry.path !== undefined === (entry.name !== undefined) || entry.path !== undefined && (typeof entry.path !== "string" || !isAbsolute22(entry.path)) || entry.name !== undefined && (typeof entry.name !== "string" || !entry.name.trim())))
|
|
44487
44797
|
return [];
|
|
44488
44798
|
if (rows.some((entry) => entry.name !== undefined && entry.enabled !== false))
|
|
44489
44799
|
return [];
|
|
44490
44800
|
const settings = new Map;
|
|
44491
44801
|
for (const entry of rows) {
|
|
44492
|
-
if (typeof entry.path !== "string" || !
|
|
44802
|
+
if (typeof entry.path !== "string" || !isAbsolute22(entry.path))
|
|
44493
44803
|
continue;
|
|
44494
44804
|
let document2;
|
|
44495
44805
|
try {
|
|
@@ -44501,7 +44811,7 @@ function disabledCodexSkillPaths(config, aliases) {
|
|
|
44501
44811
|
continue;
|
|
44502
44812
|
settings.set(document2, [...settings.get(document2) ?? [], entry.enabled === false]);
|
|
44503
44813
|
}
|
|
44504
|
-
return [...settings].filter(([, values]) => values.length === 1 && values[0] === true).map(([document2]) =>
|
|
44814
|
+
return [...settings].filter(([, values]) => values.length === 1 && values[0] === true).map(([document2]) => dirname18(document2));
|
|
44505
44815
|
}
|
|
44506
44816
|
function recheckRootAliases(aliases) {
|
|
44507
44817
|
for (const binding of aliases) {
|
|
@@ -44543,7 +44853,7 @@ function readNativeBytes(path, maximum = 64 * 1024 * 1024) {
|
|
|
44543
44853
|
}
|
|
44544
44854
|
}
|
|
44545
44855
|
function treeHash(root2) {
|
|
44546
|
-
const hash2 =
|
|
44856
|
+
const hash2 = createHash25("sha256");
|
|
44547
44857
|
let bytes = 0, files = 0;
|
|
44548
44858
|
function visit2(path) {
|
|
44549
44859
|
const stat2 = lstatSync23(path);
|
|
@@ -44575,20 +44885,20 @@ function selectNativeMigrationTargets(inventory, manifest) {
|
|
|
44575
44885
|
const identities = new Set;
|
|
44576
44886
|
const selected = [];
|
|
44577
44887
|
for (const target of manifest.targets) {
|
|
44578
|
-
if (!
|
|
44888
|
+
if (!isAbsolute22(target.projectRoot) || resolve20(target.projectRoot) !== target.projectRoot)
|
|
44579
44889
|
throw new Error(`Native migration target project root must be an existing absolute directory: ${target.projectRoot}`);
|
|
44580
|
-
const projectRoot = canonicalSystemPath(target.projectRoot), normalized = relative5(projectRoot,
|
|
44890
|
+
const projectRoot = canonicalSystemPath(target.projectRoot), normalized = relative5(projectRoot, resolve20(projectRoot, target.path));
|
|
44581
44891
|
if (!existsSync7(projectRoot) || !lstatSync23(projectRoot).isDirectory())
|
|
44582
44892
|
throw new Error(`Native migration target project root must be an existing absolute directory: ${target.projectRoot}`);
|
|
44583
44893
|
assertSafePath(projectRoot);
|
|
44584
|
-
if (
|
|
44894
|
+
if (isAbsolute22(target.path) || target.path.includes("\\") || target.path.includes("\x00") || !normalized || normalized === ".." || normalized.startsWith(`..${sep7}`) || normalized !== target.path || !/^[0-9a-f]{64}$/.test(target.treeSha256))
|
|
44585
44895
|
throw new Error(`Invalid native migration target: ${target.path}`);
|
|
44586
44896
|
const identity5 = `${target.agent}\x00${canonicalSystemPath(projectRoot)}\x00${normalized}`;
|
|
44587
44897
|
if (identities.has(identity5))
|
|
44588
44898
|
throw new Error(`Duplicate native migration target: ${target.path}`);
|
|
44589
44899
|
identities.add(identity5);
|
|
44590
|
-
const expected = canonicalSystemPath(
|
|
44591
|
-
const matches = inventory.filter((entry2) => entry2.agent === target.agent &&
|
|
44900
|
+
const expected = canonicalSystemPath(resolve20(target.projectRoot, target.path));
|
|
44901
|
+
const matches = inventory.filter((entry2) => entry2.agent === target.agent && resolve20(entry2.path) === expected);
|
|
44592
44902
|
if (matches.length !== 1)
|
|
44593
44903
|
throw new Error(`Native migration target was not found exactly once: ${target.agent} ${target.projectRoot}/${target.path}`);
|
|
44594
44904
|
const entry = matches[0];
|
|
@@ -44607,7 +44917,7 @@ function projectAncestorDirectories(projects) {
|
|
|
44607
44917
|
if (depth >= 100)
|
|
44608
44918
|
throw new Error("NATIVE_SKILL_DRIFT: project ancestor discovery limit exceeded");
|
|
44609
44919
|
directories.add(path);
|
|
44610
|
-
const parent =
|
|
44920
|
+
const parent = dirname18(path);
|
|
44611
44921
|
if (parent === path)
|
|
44612
44922
|
break;
|
|
44613
44923
|
path = parent;
|
|
@@ -44616,7 +44926,7 @@ function projectAncestorDirectories(projects) {
|
|
|
44616
44926
|
return [...directories];
|
|
44617
44927
|
}
|
|
44618
44928
|
function isCodexSkillDiscoveryInput(path) {
|
|
44619
|
-
for (let cursor = canonicalSystemPath(path);cursor !==
|
|
44929
|
+
for (let cursor = canonicalSystemPath(path);cursor !== dirname18(cursor); cursor = dirname18(cursor)) {
|
|
44620
44930
|
if (ROOTS.some(([agent, root2]) => agent === "codex" && cursor.endsWith(join27(sep7, root2))))
|
|
44621
44931
|
return true;
|
|
44622
44932
|
}
|
|
@@ -44624,9 +44934,9 @@ function isCodexSkillDiscoveryInput(path) {
|
|
|
44624
44934
|
}
|
|
44625
44935
|
function inventoryNativeSkills(home = homedir3(), options = {}) {
|
|
44626
44936
|
home = canonicalSystemPath(home);
|
|
44627
|
-
if (options.reviewedCacheAlias !== undefined && (!options.includeVendor || !
|
|
44937
|
+
if (options.reviewedCacheAlias !== undefined && (!options.includeVendor || !isAbsolute22(options.reviewedCacheAlias) || resolve20(options.reviewedCacheAlias) !== options.reviewedCacheAlias))
|
|
44628
44938
|
throw new Error("A reviewed cache alias requires vendor inventory and an exact absolute path");
|
|
44629
|
-
if (options.disabledVendorPaths?.some((path) => !
|
|
44939
|
+
if (options.disabledVendorPaths?.some((path) => !isAbsolute22(path) || resolve20(path) !== path))
|
|
44630
44940
|
throw new Error("Disabled vendor paths must be exact absolute paths");
|
|
44631
44941
|
const reviewedCacheAlias = options.reviewedCacheAlias === undefined ? undefined : canonicalSystemPath(options.reviewedCacheAlias);
|
|
44632
44942
|
const disabledVendorPaths = new Set((options.disabledVendorPaths ?? []).map(canonicalSystemPath));
|
|
@@ -44645,7 +44955,7 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
|
|
|
44645
44955
|
roots.push(["sumi", canonicalAgentPath(join27(project, directory, name), aliases)]);
|
|
44646
44956
|
}
|
|
44647
44957
|
const installationInputs = options.codexInstallationInputRoots ?? [];
|
|
44648
|
-
if (installationInputs.some((input) =>
|
|
44958
|
+
if (installationInputs.some((input) => resolve20(input) !== input || realpathSync11(input) !== input || roots.some(([agent, path]) => agent === "codex" && (path === input || path.startsWith(input + sep7) || input.startsWith(path + sep7)))))
|
|
44649
44959
|
throw new Error("Native installation input overlaps an unconditional skill-loading root");
|
|
44650
44960
|
const entries = [], seen = new Set;
|
|
44651
44961
|
const cacheScans = new Map, maxAliasProofEntries = 1e4;
|
|
@@ -44659,11 +44969,11 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
|
|
|
44659
44969
|
}
|
|
44660
44970
|
let reviewedCacheAliasFound = false;
|
|
44661
44971
|
function verifiedSiblingCacheAlias(agent, path, parent) {
|
|
44662
|
-
const link =
|
|
44663
|
-
if (
|
|
44972
|
+
const link = readlinkSync7(path), lexicalTarget = resolve20(parent, link);
|
|
44973
|
+
if (isAbsolute22(link) ? link !== lexicalTarget : dirname18(link) !== ".")
|
|
44664
44974
|
return false;
|
|
44665
44975
|
const target = canonicalSystemPath(lexicalTarget);
|
|
44666
|
-
if (
|
|
44976
|
+
if (dirname18(target) !== parent)
|
|
44667
44977
|
return false;
|
|
44668
44978
|
if (!lstatSync23(target, { throwIfNoEntry: false })?.isDirectory())
|
|
44669
44979
|
return false;
|
|
@@ -44712,17 +45022,17 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
|
|
|
44712
45022
|
}
|
|
44713
45023
|
const bridge = (!vendor || agent === "sumi") && isOwnedCliBridge(path, bridgePaths);
|
|
44714
45024
|
const rootAlias = aliases.find((item) => path === item.target || path.startsWith(item.target + sep7));
|
|
44715
|
-
entries.push({ agent, path, hash: treeHash(path), managed, vendor, ...agent === "codex" || isCodexSkillDiscoveryInput(path) ? { codexHome: process.env.CODEX_HOME ?? join27(home, ".codex") } : {}, ...agent === "codex" && path.startsWith(canonicalAgentPath(join27(home, ".codex", "skills", ".system"), aliases) + sep7) ? { system: true } : {}, ...bridge ? { bridge: true, bridgeHome:
|
|
45025
|
+
entries.push({ agent, path, hash: treeHash(path), managed, vendor, ...agent === "codex" || isCodexSkillDiscoveryInput(path) ? { codexHome: process.env.CODEX_HOME ?? join27(home, ".codex") } : {}, ...agent === "codex" && path.startsWith(canonicalAgentPath(join27(home, ".codex", "skills", ".system"), aliases) + sep7) ? { system: true } : {}, ...bridge ? { bridge: true, bridgeHome: resolve20(home) } : {}, ...rootAlias ? { rootAlias } : {} });
|
|
44716
45026
|
return scan;
|
|
44717
45027
|
}
|
|
44718
45028
|
if (depth > (agent === "sumi" ? 32 : vendor ? 32 : 3))
|
|
44719
45029
|
return { ...scan, complete: false };
|
|
44720
45030
|
const children = [], directory = opendirSync5(path);
|
|
44721
45031
|
try {
|
|
44722
|
-
let
|
|
44723
|
-
while ((
|
|
44724
|
-
admit(join27(path,
|
|
44725
|
-
children.push(
|
|
45032
|
+
let child2;
|
|
45033
|
+
while ((child2 = directory.readSync()) !== null) {
|
|
45034
|
+
admit(join27(path, child2.name));
|
|
45035
|
+
children.push(child2);
|
|
44726
45036
|
}
|
|
44727
45037
|
} finally {
|
|
44728
45038
|
directory.closeSync();
|
|
@@ -44738,15 +45048,15 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
|
|
|
44738
45048
|
const isVendor = vendor || name === ".system";
|
|
44739
45049
|
if (isVendor && !options.includeVendor)
|
|
44740
45050
|
continue;
|
|
44741
|
-
const
|
|
44742
|
-
if (isVendor && lstatSync23(
|
|
44743
|
-
const target = statSync7(
|
|
44744
|
-
if (target?.isFile() || pluginCache && target?.isDirectory() && verifiedSiblingCacheAlias(agent,
|
|
45051
|
+
const child2 = join27(path, name);
|
|
45052
|
+
if (isVendor && lstatSync23(child2, { throwIfNoEntry: false })?.isSymbolicLink()) {
|
|
45053
|
+
const target = statSync7(child2, { throwIfNoEntry: false });
|
|
45054
|
+
if (target?.isFile() || pluginCache && target?.isDirectory() && verifiedSiblingCacheAlias(agent, child2, path)) {
|
|
44745
45055
|
scan.entries++;
|
|
44746
45056
|
continue;
|
|
44747
45057
|
}
|
|
44748
45058
|
}
|
|
44749
|
-
const childScan = visit2(agent,
|
|
45059
|
+
const childScan = visit2(agent, child2, isVendor, depth + 1, pluginCache, true, configuredRoot);
|
|
44750
45060
|
scan.complete &&= childScan.complete;
|
|
44751
45061
|
scan.hasSkills ||= childScan.hasSkills;
|
|
44752
45062
|
scan.entries += childScan.entries;
|
|
@@ -44882,7 +45192,7 @@ function configureHooks(config, agent, command, profileId, nativeReady) {
|
|
|
44882
45192
|
function disableCodexSkills(text2, skills, aliases, bridgePath) {
|
|
44883
45193
|
const bundled = disableCodexBundledSkills(text2);
|
|
44884
45194
|
let result = normalizeCodexInlinePathConfig(bundled);
|
|
44885
|
-
const bridgeSelector = (entry) => typeof entry.name === "string" && entry.name.trim() === CLI_BRIDGE_NAME || typeof entry.path === "string" && [
|
|
45195
|
+
const bridgeSelector = (entry) => typeof entry.name === "string" && entry.name.trim() === CLI_BRIDGE_NAME || typeof entry.path === "string" && [resolve20(bridgePath), resolve20(join27(bridgePath, "SKILL.md"))].includes(canonicalAgentPath(entry.path, aliases));
|
|
44886
45196
|
const previousConfig = Bun.TOML.parse(bundled).skills?.config;
|
|
44887
45197
|
if (previousConfig !== undefined && (!Array.isArray(previousConfig) || previousConfig.some((entry) => !entry || typeof entry !== "object" || entry.path !== undefined && entry.name !== undefined)))
|
|
44888
45198
|
throw new Error("Codex skill controls require one path or name selector per [[skills.config]] entry; review ambiguous entries before running skills hook install");
|
|
@@ -44894,7 +45204,7 @@ function disableCodexSkills(text2, skills, aliases, bridgePath) {
|
|
|
44894
45204
|
result = result.replace(CODEX_SKILL_CONFIG_SECTIONS, (section) => {
|
|
44895
45205
|
const parsed = Bun.TOML.parse(section);
|
|
44896
45206
|
const declared = parsed.skills?.config?.[0];
|
|
44897
|
-
if (!declared || !(skill.enabled && bridgeSelector(declared)) && !(typeof declared.path === "string" && [
|
|
45207
|
+
if (!declared || !(skill.enabled && bridgeSelector(declared)) && !(typeof declared.path === "string" && [resolve20(path), resolve20(skill.path)].includes(canonicalAgentPath(declared.path, aliases))))
|
|
44898
45208
|
return section;
|
|
44899
45209
|
found = true;
|
|
44900
45210
|
return /^\s*enabled\s*=/m.test(section) ? section.replace(/^\s*enabled\s*=.*$/m, `enabled = ${skill.enabled}`) : `${section.trimEnd()}
|
|
@@ -44915,7 +45225,7 @@ enabled = false
|
|
|
44915
45225
|
return result;
|
|
44916
45226
|
}
|
|
44917
45227
|
function assertCodexInstallationInputs(home, projectDirs, inputs) {
|
|
44918
|
-
const nativeRoots = [home, ...projectAncestorDirectories(projectDirs)].flatMap((directory) => ROOTS.filter(([agent]) => agent === "codex").map(([, path]) =>
|
|
45228
|
+
const nativeRoots = [home, ...projectAncestorDirectories(projectDirs)].flatMap((directory) => ROOTS.filter(([agent]) => agent === "codex").map(([, path]) => resolve20(directory, path)));
|
|
44919
45229
|
if (inputs.some((input) => nativeRoots.some((root2) => root2 === input || root2.startsWith(input + sep7) || input.startsWith(root2 + sep7))))
|
|
44920
45230
|
throw new Error("Native installation input overlaps an unconditional skill-loading root");
|
|
44921
45231
|
}
|
|
@@ -44931,9 +45241,9 @@ function planAgentIntegration(options) {
|
|
|
44931
45241
|
throw new Error("Invalid existing Skills bridge policy");
|
|
44932
45242
|
if (policy.bridge?.agents !== undefined && (!Array.isArray(policy.bridge.agents) || policy.bridge.agents.some((agent) => !INTEGRATION_AGENTS.includes(agent))))
|
|
44933
45243
|
throw new Error("Invalid existing bridge agent inventory");
|
|
44934
|
-
for (const
|
|
44935
|
-
if (policy.bridge?.[
|
|
44936
|
-
throw new Error(`Invalid existing bridge ${
|
|
45244
|
+
for (const field3 of ["commands", "profiles"])
|
|
45245
|
+
if (policy.bridge?.[field3] !== undefined && (!policy.bridge[field3] || typeof policy.bridge[field3] !== "object" || Array.isArray(policy.bridge[field3]) || Object.entries(policy.bridge[field3]).some(([key, value]) => !INTEGRATION_AGENTS.includes(key) || typeof value !== "string" || !value || value.includes("\x00"))))
|
|
45246
|
+
throw new Error(`Invalid existing bridge ${field3} binding`);
|
|
44937
45247
|
const priorAgents = policy.bridge?.agents ?? [];
|
|
44938
45248
|
const profileId = options.profileId ?? policy.profileId ?? "default";
|
|
44939
45249
|
const validateProfile = (value) => {
|
|
@@ -44948,13 +45258,18 @@ function planAgentIntegration(options) {
|
|
|
44948
45258
|
return [agent, { command, profileId: profileId2 }];
|
|
44949
45259
|
}));
|
|
44950
45260
|
const retainedAgents = [];
|
|
45261
|
+
const priorExecutables = policy.bridge?.discoveryExecutables ?? {};
|
|
45262
|
+
const executables = new Map;
|
|
44951
45263
|
const discoveries = [...new Set(options.agents)].map((agent) => {
|
|
45264
|
+
const prior = priorExecutables[agent];
|
|
45265
|
+
const executable2 = discoveryExecutable(agent) ?? (prior ? recordedDiscoveryExecutable(agent, prior) : null);
|
|
45266
|
+
executables.set(agent, executable2);
|
|
44952
45267
|
const retainedReview = options.discoveryInputs === undefined && policy.bridge?.discovery?.[agent]?.method === "reviewed" ? { ...policy.bridge.discovery[agent], ...agent === "codex" ? { codexDisabledPluginSkills: policy.bridge.codexPluginSkills ?? [] } : {} } : undefined;
|
|
44953
45268
|
if (retainedReview) {
|
|
44954
45269
|
assertManagedAgentBridge(agent, { home, dataDir: dataDir2, projectDir: options.projectDir ?? home });
|
|
44955
45270
|
retainedAgents.push(agent);
|
|
44956
45271
|
}
|
|
44957
|
-
return resolveAgentDiscovery({ home, agent, reviewed: options.discoveryInputs, retainedReview, canonical: (path) => canonicalAgentPath(path, aliases) });
|
|
45272
|
+
return resolveAgentDiscovery({ home, agent, reviewed: options.discoveryInputs, retainedReview, canonical: (path) => canonicalAgentPath(path, aliases), executable: executable2 });
|
|
44958
45273
|
});
|
|
44959
45274
|
const codexConfigBefore = options.agents.includes("codex") ? readOptional(canonicalAgentPath(join27(home, ".codex", "config.toml"), aliases)) : null;
|
|
44960
45275
|
const codexConfig = Bun.TOML.parse(codexConfigBefore ?? "");
|
|
@@ -44962,7 +45277,7 @@ function planAgentIntegration(options) {
|
|
|
44962
45277
|
const codexPathConfig = options.agents.includes("codex") ? disableCodexSkills(codexConfigBefore ?? "", nativeSkills, aliases, canonicalAgentPath(join27(home, ".codex/skills", CLI_BRIDGE_NAME), aliases)) : undefined;
|
|
44963
45278
|
const plannedCodexRules = codexPathConfig === undefined ? undefined : Bun.TOML.parse(codexPathConfig).skills?.config ?? [];
|
|
44964
45279
|
const observedNativeSources = [];
|
|
44965
|
-
const codexPluginControls = options.codexNativeCatalog ? reviewCodexPluginControls(options.codexNativeCatalog, nativeSkills.filter((entry) => entry.agent === "codex" && entry.vendor).map((entry) => join27(entry.path, "SKILL.md")), canonicalAgentPath(join27(home, ".codex/plugins/cache"), aliases),
|
|
45280
|
+
const codexPluginControls = options.codexNativeCatalog ? reviewCodexPluginControls(options.codexNativeCatalog, nativeSkills.filter((entry) => entry.agent === "codex" && entry.vendor).map((entry) => join27(entry.path, "SKILL.md")), canonicalAgentPath(join27(home, ".codex/plugins/cache"), aliases), resolve20(options.projectDir ?? home), (path) => {
|
|
44966
45281
|
const bytes = readNativeBytes(path, 1024 * 1024);
|
|
44967
45282
|
observedNativeSources.push({ path, sha256: sha4(bytes) });
|
|
44968
45283
|
return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
@@ -45083,7 +45398,7 @@ function planAgentIntegration(options) {
|
|
|
45083
45398
|
const { codexInstallationInputs: previousInputs, ...current } = rebound;
|
|
45084
45399
|
const inputs = codexPluginSourceInputs.map((input) => input.sourceRoot);
|
|
45085
45400
|
const directories = options.codexNativeCatalog || !previousInputs ? captureDiscoveryDirectories((binding.directories ?? []).filter((directory) => inputs.some((root2) => root2.startsWith(directory.path + sep7))).map((directory) => directory.path), inputs) : previousInputs.directories;
|
|
45086
|
-
const installed = codexPluginSourceInputs.length ? { ...current, codexInstallationInputs: { version:
|
|
45401
|
+
const installed = codexPluginSourceInputs.length ? { ...current, codexInstallationInputs: { version: codexPluginSkillReview.version, catalogSha256: codexPluginSkillReview.catalogSha256, plugins: codexPluginSourceInputs, ...directories?.length ? { directories } : {} } } : current;
|
|
45087
45402
|
return captureRetiredCodexDiscovery(installed, codexPluginSkills, Bun.TOML.parse(changes.find((change) => change.path === canonicalAgentPath(join27(home, ".codex/config.toml"), aliases))?.after ?? codexConfigBefore ?? "").skills?.config ?? []);
|
|
45088
45403
|
});
|
|
45089
45404
|
const nextPolicy = { ...policy, version: 1, loading: "cli", profileId, bridge: {
|
|
@@ -45091,7 +45406,7 @@ function planAgentIntegration(options) {
|
|
|
45091
45406
|
version: CLI_BRIDGE_VERSION,
|
|
45092
45407
|
digest: CLI_BRIDGE_DIGEST,
|
|
45093
45408
|
agents: [...new Set([...priorAgents, ...options.agents])].sort(),
|
|
45094
|
-
home:
|
|
45409
|
+
home: resolve20(home),
|
|
45095
45410
|
includeVendor: true,
|
|
45096
45411
|
...options.agents.includes("hermes") ? { supervisors: { ...policy.bridge?.supervisors, hermes: { path: join27(dataDir2, "agent-hooks", "hermes.js"), runtime: process.execPath, sha256: sha4(renderHermesSupervisor(bindings.get("hermes").command, bindings.get("hermes").profileId)) } } } : {},
|
|
45097
45412
|
commands: { ...policy.bridge?.commands, ...Object.fromEntries([...bindings].map(([agent, binding]) => [agent, binding.command])) },
|
|
@@ -45101,19 +45416,30 @@ function planAgentIntegration(options) {
|
|
|
45101
45416
|
...options.codexNativeCatalog || codexPluginSkills.length || codexInactivePlugins.length || codexPluginSourceInputs.length ? { codexPluginSkills, codexInactivePlugins, codexPluginSkillReview } : {},
|
|
45102
45417
|
discovery: { ...policy.bridge?.discovery, ...Object.fromEntries(discoveryAfter.map((binding) => [binding.agent, binding])) }
|
|
45103
45418
|
} };
|
|
45419
|
+
const discoveryExecutables = { ...priorExecutables };
|
|
45420
|
+
for (const [agent, executable2] of executables) {
|
|
45421
|
+
if (executable2)
|
|
45422
|
+
discoveryExecutables[agent] = executable2;
|
|
45423
|
+
else
|
|
45424
|
+
delete discoveryExecutables[agent];
|
|
45425
|
+
}
|
|
45426
|
+
if (Object.keys(discoveryExecutables).length)
|
|
45427
|
+
nextPolicy.bridge.discoveryExecutables = discoveryExecutables;
|
|
45428
|
+
else
|
|
45429
|
+
delete nextPolicy.bridge.discoveryExecutables;
|
|
45104
45430
|
const serializedPolicy = serializeManagedSkillPolicy(nextPolicy);
|
|
45105
45431
|
if (JSON.stringify(policy) !== JSON.stringify(nextPolicy))
|
|
45106
45432
|
changes.push({ path: policyPath, before: previousPolicy, after: serializedPolicy });
|
|
45107
45433
|
recheckRootAliases(aliases);
|
|
45108
45434
|
return { dataDir: dataDir2, profileId, changes, nativeSkills, ...observedSettings ? { observedSettings } : {}, ...observedNativeSources.length ? { observedNativeSources } : {}, ...nextPolicy.bridge.codexPluginSkillReview ? { codexPluginSkillReview: nextPolicy.bridge.codexPluginSkillReview } : {}, observedPolicy: { path: policyPath, before: previousPolicy }, discoveryBefore: discoveries, discoveryAfter, ...aliases.length ? { rootAliases: aliases } : {}, ...retainedAgents.length ? { retainedReviewChecks: { home, projectDir: options.projectDir ?? home, agents: retainedAgents } } : {} };
|
|
45109
45435
|
}
|
|
45110
|
-
function hookProjectionRefusal(
|
|
45111
|
-
throw new Error(`CLAUDE_MANAGED_HOOK_${
|
|
45436
|
+
function hookProjectionRefusal(reason2) {
|
|
45437
|
+
throw new Error(`CLAUDE_MANAGED_HOOK_${reason2}`);
|
|
45112
45438
|
}
|
|
45113
45439
|
function projectedHookAcl(path, observed) {
|
|
45114
45440
|
if (process.platform !== "darwin")
|
|
45115
45441
|
return;
|
|
45116
|
-
const identity5 = (stat2) => `${stat2.dev}:${stat2.ino}:${stat2.ctimeNs}:${stat2.uid}:${stat2.mode}:${stat2.nlink}:${stat2.size}:${stat2.mtimeNs}`;
|
|
45442
|
+
const identity5 = observed.isDirectory() ? (stat2) => `${stat2.dev}:${stat2.ino}:${stat2.uid}:${stat2.mode}` : (stat2) => `${stat2.dev}:${stat2.ino}:${stat2.ctimeNs}:${stat2.uid}:${stat2.mode}:${stat2.nlink}:${stat2.size}:${stat2.mtimeNs}`;
|
|
45117
45443
|
const fd = openSync18(path, constants15.O_RDONLY | constants15.O_NOFOLLOW | constants15.O_NONBLOCK | (observed.isDirectory() ? constants15.O_DIRECTORY : 0));
|
|
45118
45444
|
try {
|
|
45119
45445
|
if (identity5(fstatSync18(fd, { bigint: true })) !== identity5(observed) || !hasTrustedDarwinAcl(fd, true) || identity5(fstatSync18(fd, { bigint: true })) !== identity5(observed) || identity5(lstatSync23(path, { bigint: true })) !== identity5(observed))
|
|
@@ -45124,18 +45450,18 @@ function projectedHookAcl(path, observed) {
|
|
|
45124
45450
|
}
|
|
45125
45451
|
function projectedHookExecutable(command, expectedResolved) {
|
|
45126
45452
|
try {
|
|
45127
|
-
if (!
|
|
45453
|
+
if (!isAbsolute22(command) || /[\0\r\n]/.test(command) || resolve20(command) !== command)
|
|
45128
45454
|
hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
|
|
45129
45455
|
command = canonicalSystemPath(command);
|
|
45130
45456
|
const parents3 = (file = command) => {
|
|
45131
45457
|
const result = [];
|
|
45132
|
-
for (let path =
|
|
45458
|
+
for (let path = dirname18(file);; path = dirname18(path)) {
|
|
45133
45459
|
const stat2 = lstatSync23(path, { bigint: true });
|
|
45134
|
-
if (!stat2.isDirectory() || (stat2.mode & 0o022n) !== 0n && !(stat2.uid === 0n && (stat2.mode & 0o1000n) !== 0n))
|
|
45460
|
+
if (!stat2.isDirectory() || !trustedAncestorOwner(stat2.uid) || (stat2.mode & 0o022n) !== 0n && !(stat2.uid === 0n && (stat2.mode & 0o1000n) !== 0n))
|
|
45135
45461
|
hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
|
|
45136
45462
|
projectedHookAcl(path, stat2);
|
|
45137
45463
|
result.push(`${path}:${stat2.dev}:${stat2.ino}:${stat2.uid}:${stat2.mode}`);
|
|
45138
|
-
if (
|
|
45464
|
+
if (dirname18(path) === path)
|
|
45139
45465
|
break;
|
|
45140
45466
|
}
|
|
45141
45467
|
return result;
|
|
@@ -45145,22 +45471,33 @@ function projectedHookExecutable(command, expectedResolved) {
|
|
|
45145
45471
|
hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
|
|
45146
45472
|
const linkIdentity = (stat2) => `${stat2.dev}:${stat2.ino}:${stat2.mode}:${stat2.uid}:${stat2.ctimeNs}`;
|
|
45147
45473
|
const target = resolveLauncherCommand(command), resolved = target.entry;
|
|
45474
|
+
const direct = () => link.isSymbolicLink() ? directAliasTarget(command) === target.physical : target.physical === command;
|
|
45475
|
+
if (!direct())
|
|
45476
|
+
hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
|
|
45148
45477
|
if (expectedResolved !== undefined && resolved !== expectedResolved)
|
|
45149
45478
|
hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
|
|
45150
45479
|
let launcher, launcherParentIdentity;
|
|
45480
|
+
let runtime;
|
|
45151
45481
|
if (target.pinned) {
|
|
45152
45482
|
launcherParentIdentity = parents3(target.physical);
|
|
45153
45483
|
launcher = snapshot(target.physical, false);
|
|
45154
45484
|
projectedHookAcl(launcher.file, launcher.stat);
|
|
45155
45485
|
if (launcher.sha256 !== target.pinned.sha256 || (launcher.stat.mode & 0o100n) === 0n)
|
|
45156
45486
|
hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
|
|
45157
|
-
|
|
45487
|
+
const path = target.pinned.runtime;
|
|
45488
|
+
assertPinnedLauncherRuntimeSafe(path);
|
|
45489
|
+
if (resolve20(path) !== path)
|
|
45490
|
+
hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
|
|
45491
|
+
runtime = { path, parents: parents3(path), stat: lstatSync23(path, { bigint: true }) };
|
|
45492
|
+
if (!runtime.stat.isFile())
|
|
45493
|
+
hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
|
|
45494
|
+
projectedHookAcl(path, runtime.stat);
|
|
45158
45495
|
}
|
|
45159
45496
|
const resolvedParentIdentity = parents3(resolved);
|
|
45160
|
-
const manifest = snapshot(join27(
|
|
45497
|
+
const manifest = snapshot(join27(dirname18(dirname18(resolved)), "package.json"), false, { readOnlyPackage: true });
|
|
45161
45498
|
projectedHookAcl(manifest.file, manifest.stat);
|
|
45162
45499
|
const pkg = JSON.parse(manifest.text);
|
|
45163
|
-
if (pkg.name !== "@hasna/skills" || !/^\d+\.\d+\.\d+$/.test(pkg.version) || pkg.bin?.skills !== "bin/index.js" || resolved !== join27(
|
|
45500
|
+
if (pkg.name !== "@hasna/skills" || !/^\d+\.\d+\.\d+$/.test(pkg.version) || pkg.bin?.skills !== "bin/index.js" || resolved !== join27(dirname18(manifest.file), "bin/index.js"))
|
|
45164
45501
|
hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
|
|
45165
45502
|
const cli = snapshot(resolved, false, { readOnlyPackage: true });
|
|
45166
45503
|
projectedHookAcl(cli.file, cli.stat);
|
|
@@ -45169,7 +45506,7 @@ function projectedHookExecutable(command, expectedResolved) {
|
|
|
45169
45506
|
const recheck = () => {
|
|
45170
45507
|
try {
|
|
45171
45508
|
const again = resolveLauncherCommand(command);
|
|
45172
|
-
if (again.entry !== resolved || again.physical !== target.physical || linkIdentity(lstatSync23(command, { bigint: true })) !== linkIdentity(link) || !isDeepStrictEqual8(parents3(), parentIdentity) || !isDeepStrictEqual8(parents3(resolved), resolvedParentIdentity))
|
|
45509
|
+
if (again.entry !== resolved || again.physical !== target.physical || linkIdentity(lstatSync23(command, { bigint: true })) !== linkIdentity(link) || !direct() || !isDeepStrictEqual8(parents3(), parentIdentity) || !isDeepStrictEqual8(parents3(resolved), resolvedParentIdentity))
|
|
45173
45510
|
hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
|
|
45174
45511
|
if (launcher) {
|
|
45175
45512
|
if (!isDeepStrictEqual8(parents3(target.physical), launcherParentIdentity))
|
|
@@ -45177,6 +45514,12 @@ function projectedHookExecutable(command, expectedResolved) {
|
|
|
45177
45514
|
projectedHookAcl(launcher.file, launcher.stat);
|
|
45178
45515
|
unchanged2(launcher);
|
|
45179
45516
|
}
|
|
45517
|
+
if (runtime) {
|
|
45518
|
+
assertPinnedLauncherRuntimeSafe(runtime.path);
|
|
45519
|
+
if (!isDeepStrictEqual8(parents3(runtime.path), runtime.parents))
|
|
45520
|
+
hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
|
|
45521
|
+
projectedHookAcl(runtime.path, runtime.stat);
|
|
45522
|
+
}
|
|
45180
45523
|
projectedHookAcl(cli.file, cli.stat);
|
|
45181
45524
|
projectedHookAcl(manifest.file, manifest.stat);
|
|
45182
45525
|
unchanged2(cli);
|
|
@@ -45203,7 +45546,7 @@ function planClaudeManagedHookProjection(options) {
|
|
|
45203
45546
|
} catch {
|
|
45204
45547
|
hookProjectionRefusal("TARGET_INVALID");
|
|
45205
45548
|
}
|
|
45206
|
-
const home =
|
|
45549
|
+
const home = resolve20(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
|
|
45207
45550
|
const policyPath = join27(dataDir2, "agent-policy.json");
|
|
45208
45551
|
let policyBytes, settingsBytes, settingsPath, command, profile;
|
|
45209
45552
|
try {
|
|
@@ -45295,29 +45638,28 @@ function planClaudePreToolUseHookUpdate(options) {
|
|
|
45295
45638
|
return planClaudeHookEventsUpdate({ ...options, events: ["PreToolUse"] });
|
|
45296
45639
|
}
|
|
45297
45640
|
function claudeSettingsConsumers(home, path, discoveries, aliases) {
|
|
45298
|
-
const
|
|
45641
|
+
const canonical8 = (value) => canonicalAgentPath(value, aliases);
|
|
45299
45642
|
const containsSettings = (root2) => {
|
|
45300
|
-
const distance = relative5(
|
|
45301
|
-
return distance === "" || distance !== ".." && !distance.startsWith(`..${sep7}`) && !
|
|
45643
|
+
const distance = relative5(canonical8(root2), path);
|
|
45644
|
+
return distance === "" || distance !== ".." && !distance.startsWith(`..${sep7}`) && !isAbsolute22(distance);
|
|
45302
45645
|
};
|
|
45303
|
-
return discoveries.filter((binding) => binding.agent === "claude" || binding.agent === "opencode" ||
|
|
45646
|
+
return discoveries.filter((binding) => binding.agent === "claude" || binding.agent === "opencode" || canonical8(join27(home, AGENT_ADAPTERS[binding.agent].config)) === path || binding.sources.some((source) => canonical8(source.path) === path) || binding.roots.some(containsSettings) || binding.directories?.some((directory) => containsSettings(directory.path))).map((binding) => binding.agent);
|
|
45304
45647
|
}
|
|
45305
|
-
function verifyCoordinatedDiscovery(binding, home, aliases) {
|
|
45648
|
+
function verifyCoordinatedDiscovery(binding, home, aliases, executable2) {
|
|
45306
45649
|
try {
|
|
45307
45650
|
if (binding.method !== "automatic" && binding.method !== "reviewed")
|
|
45308
45651
|
throw new Error("Invalid managed discovery method");
|
|
45309
45652
|
verifyAgentDiscovery(binding);
|
|
45310
|
-
if (binding.method === "automatic")
|
|
45311
|
-
|
|
45312
|
-
if (JSON.stringify(current) !== JSON.stringify(binding))
|
|
45313
|
-
throw new Error("Configured native discovery roots changed during Claude update");
|
|
45314
|
-
}
|
|
45653
|
+
if (binding.method === "automatic")
|
|
45654
|
+
verifyAutomaticDiscoveryClosure(binding, { home, canonical: (path) => canonicalAgentPath(path, aliases), change: "Configured native discovery roots changed during Claude update", executable: executable2 });
|
|
45315
45655
|
} catch (error) {
|
|
45656
|
+
if (isDiscoveryRootUnresolved(error))
|
|
45657
|
+
throw error;
|
|
45316
45658
|
throw new Error(`NATIVE_SKILL_DRIFT: ${error.message}`);
|
|
45317
45659
|
}
|
|
45318
45660
|
}
|
|
45319
45661
|
function planClaudeHookEventsUpdate(options) {
|
|
45320
|
-
const home =
|
|
45662
|
+
const home = resolve20(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
|
|
45321
45663
|
const policyPath = join27(dataDir2, "agent-policy.json");
|
|
45322
45664
|
assertSafePath(policyPath);
|
|
45323
45665
|
const snapshot2 = readManagedSkillPolicySnapshot(dataDir2);
|
|
@@ -45343,8 +45685,9 @@ function planClaudeHookEventsUpdate(options) {
|
|
|
45343
45685
|
});
|
|
45344
45686
|
if (discoveries.length !== agents.length || !agents.includes("claude"))
|
|
45345
45687
|
throw new Error("Missing managed Claude discovery coverage");
|
|
45688
|
+
const discoveryExecutables = bridge.discoveryExecutables;
|
|
45346
45689
|
for (const binding of discoveries)
|
|
45347
|
-
verifyCoordinatedDiscovery(binding, home, aliases);
|
|
45690
|
+
verifyCoordinatedDiscovery(binding, home, aliases, discoveryExecutables?.[binding.agent]);
|
|
45348
45691
|
const consumers = claudeSettingsConsumers(home, path, discoveries, aliases);
|
|
45349
45692
|
for (const agent of consumers)
|
|
45350
45693
|
assertManagedAgentBridge(agent, { home, dataDir: dataDir2, projectDir: home });
|
|
@@ -45379,13 +45722,14 @@ function planClaudeHookEventsUpdate(options) {
|
|
|
45379
45722
|
observedPolicy: { path: policyPath, before: snapshot2.text },
|
|
45380
45723
|
discoveryBefore: discoveries,
|
|
45381
45724
|
discoveryAfter,
|
|
45725
|
+
...discoveryExecutables ? { discoveryExecutables } : {},
|
|
45382
45726
|
rootAliases: aliases,
|
|
45383
45727
|
managedAgentChecks: { home, agents: consumers }
|
|
45384
45728
|
};
|
|
45385
45729
|
}
|
|
45386
45730
|
function atomicWrite2(path, content) {
|
|
45387
45731
|
assertSafePath(path);
|
|
45388
|
-
mkdirSync6(
|
|
45732
|
+
mkdirSync6(dirname18(path), { recursive: true, mode: 448 });
|
|
45389
45733
|
const temporary = `${path}.skills-${randomUUID4()}`;
|
|
45390
45734
|
try {
|
|
45391
45735
|
writeFileSync5(temporary, content, { mode: 384, flag: "wx" });
|
|
@@ -45400,7 +45744,7 @@ function planAgentSettingsWitnessUpgrade(options) {
|
|
|
45400
45744
|
throw new Error("Invalid Codex witness target version");
|
|
45401
45745
|
if (options.targetClaudeVersion !== undefined && (options.agent !== "claude" || ![3, 4].includes(options.targetClaudeVersion)))
|
|
45402
45746
|
throw new Error("Invalid Claude witness target version");
|
|
45403
|
-
const home =
|
|
45747
|
+
const home = resolve20(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
|
|
45404
45748
|
const snapshot2 = readManagedSkillPolicySnapshot(dataDir2);
|
|
45405
45749
|
if (!snapshot2 || sha4(snapshot2.text) !== options.expectedPolicySha256)
|
|
45406
45750
|
throw new Error("Managed policy preimage changed");
|
|
@@ -45460,7 +45804,7 @@ function planAgentSettingsWitnessUpgrade(options) {
|
|
|
45460
45804
|
const replacement = { ...binding, sources: rebound };
|
|
45461
45805
|
verifyAgentDiscovery(replacement);
|
|
45462
45806
|
const after = serializeManagedSkillPolicy({ ...policy, bridge: { ...policy.bridge, discovery: { ...policy.bridge.discovery, [options.agent]: replacement } } });
|
|
45463
|
-
return { dataDir: dataDir2, profileId: policy.profileId, changes: [{ path: join27(dataDir2, "agent-policy.json"), before: snapshot2.text, after }], nativeSkills: [], observedPolicy: { path: join27(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 })) } };
|
|
45807
|
+
return { dataDir: dataDir2, profileId: policy.profileId, changes: [{ path: join27(dataDir2, "agent-policy.json"), before: snapshot2.text, after }], nativeSkills: [], observedPolicy: { path: join27(dataDir2, "agent-policy.json"), before: snapshot2.text }, observedSettings: { path: configPath, before: settings }, discoveryBefore: [replacement], discoveryAfter: [replacement], ...policy.bridge.discoveryExecutables ? { discoveryExecutables: policy.bridge.discoveryExecutables } : {}, 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 })) } };
|
|
45464
45808
|
}
|
|
45465
45809
|
function applyAgentIntegration(plan, options = {}) {
|
|
45466
45810
|
const roots = plan.changes.flatMap((change) => {
|
|
@@ -45478,10 +45822,10 @@ function applyAgentIntegrationUnlocked(plan, options = {}, assertCurrent) {
|
|
|
45478
45822
|
throw new Error("Native settings changed after witness planning");
|
|
45479
45823
|
const policyPath = join27(plan.dataDir, "agent-policy.json");
|
|
45480
45824
|
assertSafePath(policyPath);
|
|
45481
|
-
const currentText = (path) =>
|
|
45825
|
+
const currentText = (path) => resolve20(path) === resolve20(policyPath) ? readManagedSkillPolicySnapshot(plan.dataDir)?.text ?? null : readOptional(path);
|
|
45482
45826
|
readManagedSkillPolicySnapshot(plan.dataDir);
|
|
45483
45827
|
for (const change of plan.changes)
|
|
45484
|
-
if (
|
|
45828
|
+
if (resolve20(change.path) === resolve20(policyPath))
|
|
45485
45829
|
parseManagedSkillPolicy(change.after);
|
|
45486
45830
|
const aliases = plan.rootAliases ?? [];
|
|
45487
45831
|
assertCurrent();
|
|
@@ -45502,7 +45846,7 @@ function applyAgentIntegrationUnlocked(plan, options = {}, assertCurrent) {
|
|
|
45502
45846
|
assertManagedAgentBridgeWithDiscovery(agent, { home: plan.managedAgentChecks.home, dataDir: plan.dataDir, projectDir: plan.managedAgentChecks.home }, provenDiscovery?.agent === agent ? provenDiscovery : undefined);
|
|
45503
45847
|
for (const binding of plan.discoveryBefore ?? []) {
|
|
45504
45848
|
if (plan.managedAgentChecks)
|
|
45505
|
-
verifyCoordinatedDiscovery(binding, plan.managedAgentChecks.home, aliases);
|
|
45849
|
+
verifyCoordinatedDiscovery(binding, plan.managedAgentChecks.home, aliases, plan.discoveryExecutables?.[binding.agent]);
|
|
45506
45850
|
else
|
|
45507
45851
|
verifyAgentDiscovery(binding);
|
|
45508
45852
|
}
|
|
@@ -45534,7 +45878,7 @@ function applyAgentIntegrationUnlocked(plan, options = {}, assertCurrent) {
|
|
|
45534
45878
|
recheckRootAliases(aliases);
|
|
45535
45879
|
if (currentText(change.path) !== change.before)
|
|
45536
45880
|
throw new Error(`Configuration changed after planning: ${change.path}`);
|
|
45537
|
-
for (let directory =
|
|
45881
|
+
for (let directory = dirname18(change.path);!existsSync7(directory); directory = dirname18(directory))
|
|
45538
45882
|
createdDirectories.add(directory);
|
|
45539
45883
|
const after = change.after;
|
|
45540
45884
|
atomicWrite2(change.path, after);
|
|
@@ -45549,7 +45893,7 @@ function applyAgentIntegrationUnlocked(plan, options = {}, assertCurrent) {
|
|
|
45549
45893
|
throw new Error("Native settings changed during witness application");
|
|
45550
45894
|
for (const binding of plan.discoveryAfter ?? []) {
|
|
45551
45895
|
if (plan.managedAgentChecks)
|
|
45552
|
-
verifyCoordinatedDiscovery(binding, plan.managedAgentChecks.home, aliases);
|
|
45896
|
+
verifyCoordinatedDiscovery(binding, plan.managedAgentChecks.home, aliases, plan.discoveryExecutables?.[binding.agent]);
|
|
45553
45897
|
else
|
|
45554
45898
|
verifyAgentDiscovery(binding);
|
|
45555
45899
|
}
|
|
@@ -45606,7 +45950,7 @@ function writeArchiveJournal(path, value) {
|
|
|
45606
45950
|
closeSync18(descriptor);
|
|
45607
45951
|
descriptor = undefined;
|
|
45608
45952
|
renameSync4(temporary, path);
|
|
45609
|
-
syncArchiveDirectory(
|
|
45953
|
+
syncArchiveDirectory(dirname18(path));
|
|
45610
45954
|
} finally {
|
|
45611
45955
|
if (descriptor !== undefined)
|
|
45612
45956
|
closeSync18(descriptor);
|
|
@@ -45664,14 +46008,14 @@ function archiveNativeSkillsUnlocked(inventory, options, assertCurrent) {
|
|
|
45664
46008
|
};
|
|
45665
46009
|
assertSafePath(archiveRoot);
|
|
45666
46010
|
const created = [];
|
|
45667
|
-
for (let path = archiveRoot;!existsSync7(path); path =
|
|
46011
|
+
for (let path = archiveRoot;!existsSync7(path); path = dirname18(path))
|
|
45668
46012
|
created.push(path);
|
|
45669
46013
|
mkdirSync6(archiveRoot, { recursive: true, mode: 448 });
|
|
45670
46014
|
try {
|
|
45671
46015
|
for (const directory of created)
|
|
45672
46016
|
syncArchiveDirectory(directory);
|
|
45673
46017
|
if (created.length)
|
|
45674
|
-
syncArchiveDirectory(
|
|
46018
|
+
syncArchiveDirectory(dirname18(created.at(-1)));
|
|
45675
46019
|
writeArchiveJournal(receiptPath, journal);
|
|
45676
46020
|
for (const [index, entry] of selected.entries()) {
|
|
45677
46021
|
assertCurrent();
|
|
@@ -45684,7 +46028,7 @@ function archiveNativeSkillsUnlocked(inventory, options, assertCurrent) {
|
|
|
45684
46028
|
writeArchiveJournal(receiptPath, journal);
|
|
45685
46029
|
renameSync4(move.source, move.archive);
|
|
45686
46030
|
moved.push(move);
|
|
45687
|
-
syncArchiveDirectory(
|
|
46031
|
+
syncArchiveDirectory(dirname18(move.source));
|
|
45688
46032
|
syncArchiveDirectory(archiveRoot);
|
|
45689
46033
|
verifyArchive(move);
|
|
45690
46034
|
move.status = "archived";
|
|
@@ -45721,7 +46065,7 @@ function archiveNativeSkillsUnlocked(inventory, options, assertCurrent) {
|
|
|
45721
46065
|
}
|
|
45722
46066
|
if (entry.discoveryOnly) {
|
|
45723
46067
|
linkSync3(entry.archive, entry.source);
|
|
45724
|
-
syncArchiveDirectory(
|
|
46068
|
+
syncArchiveDirectory(dirname18(entry.source));
|
|
45725
46069
|
unlinkSync5(entry.archive);
|
|
45726
46070
|
} else {
|
|
45727
46071
|
if (lstatSync23(entry.source, { throwIfNoEntry: false })) {
|
|
@@ -45732,7 +46076,7 @@ function archiveNativeSkillsUnlocked(inventory, options, assertCurrent) {
|
|
|
45732
46076
|
renameSync4(entry.archive, entry.source);
|
|
45733
46077
|
}
|
|
45734
46078
|
entry.status = "restored";
|
|
45735
|
-
syncArchiveDirectory(
|
|
46079
|
+
syncArchiveDirectory(dirname18(entry.source));
|
|
45736
46080
|
syncArchiveDirectory(archiveRoot);
|
|
45737
46081
|
} catch {
|
|
45738
46082
|
entry.status = "recovery-required";
|
|
@@ -45757,7 +46101,7 @@ function isInertCodexPluginCacheCopy(entry, cache, allowedHostPaths, read3) {
|
|
|
45757
46101
|
return false;
|
|
45758
46102
|
const document2 = join27(entry.path, "SKILL.md");
|
|
45759
46103
|
const inside = relative5(cache, entry.path);
|
|
45760
|
-
if (!inside ||
|
|
46104
|
+
if (!inside || isAbsolute22(inside) || inside.split(sep7).some((segment) => segment === ".."))
|
|
45761
46105
|
return false;
|
|
45762
46106
|
assertSafePath(entry.path);
|
|
45763
46107
|
if (!lstatSync23(cache).isDirectory() || !lstatSync23(entry.path).isDirectory() || !lstatSync23(document2).isFile())
|
|
@@ -45777,7 +46121,7 @@ function assertManagedAgentBridge(agent, options = {}) {
|
|
|
45777
46121
|
assertManagedAgentBridgeWithDiscovery(agent, options);
|
|
45778
46122
|
}
|
|
45779
46123
|
function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscovery) {
|
|
45780
|
-
const home =
|
|
46124
|
+
const home = resolve20(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
|
|
45781
46125
|
assertSafePath(join27(dataDir2, "agent-policy.json"));
|
|
45782
46126
|
const snapshot2 = readManagedSkillPolicySnapshot(dataDir2);
|
|
45783
46127
|
if (!snapshot2)
|
|
@@ -45875,12 +46219,11 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
|
|
|
45875
46219
|
verifyAgentDiscovery(agent === "codex" ? { ...discovery, codexDisabledPluginSkills: binding.codexPluginSkills ?? [] } : discovery, options.codexDiscoveryRecovery);
|
|
45876
46220
|
if (agent === "sumi" && discovery.method === "reviewed")
|
|
45877
46221
|
resolveAgentDiscovery({ home, agent, retainedReview: discovery, canonical: (path) => canonicalAgentPath(path, aliases) });
|
|
45878
|
-
if (discovery.method === "automatic")
|
|
45879
|
-
|
|
45880
|
-
if (JSON.stringify(current) !== JSON.stringify(discovery))
|
|
45881
|
-
throw new Error("Configured native discovery roots changed");
|
|
45882
|
-
}
|
|
46222
|
+
if (discovery.method === "automatic")
|
|
46223
|
+
verifyAutomaticDiscoveryClosure(discovery, { home, canonical: (path) => canonicalAgentPath(path, aliases), change: "Configured native discovery roots changed", executable: binding.discoveryExecutables?.[agent] });
|
|
45883
46224
|
} catch (error) {
|
|
46225
|
+
if (isDiscoveryRootUnresolved(error))
|
|
46226
|
+
throw error;
|
|
45884
46227
|
throw new Error(`NATIVE_SKILL_DRIFT: ${error.message}`);
|
|
45885
46228
|
}
|
|
45886
46229
|
let installationInputRoots = [];
|
|
@@ -45936,13 +46279,13 @@ import {
|
|
|
45936
46279
|
statSync as statSync10,
|
|
45937
46280
|
writeFileSync as writeFileSync7
|
|
45938
46281
|
} from "fs";
|
|
45939
|
-
import { basename as
|
|
46282
|
+
import { basename as basename12, dirname as dirname21, isAbsolute as isAbsolute23, join as join31, normalize as normalize4, relative as relative7, resolve as resolve22, sep as sep10 } from "path";
|
|
45940
46283
|
|
|
45941
46284
|
// src/lib/registry-data/index.ts
|
|
45942
46285
|
var SKILLS = [];
|
|
45943
46286
|
|
|
45944
46287
|
// src/lib/skill-hash.ts
|
|
45945
|
-
import { createHash as
|
|
46288
|
+
import { createHash as createHash26 } from "crypto";
|
|
45946
46289
|
import { existsSync as existsSync8, readdirSync as readdirSync9, readFileSync as readFileSync18, statSync as statSync8 } from "fs";
|
|
45947
46290
|
import { join as join28, sep as sep8 } from "path";
|
|
45948
46291
|
var CONTENT_HASH_ALGORITHM = "sha256";
|
|
@@ -46066,13 +46409,13 @@ function* bundleHashParts(files) {
|
|
|
46066
46409
|
yield new TextEncoder().encode("\x00");
|
|
46067
46410
|
}
|
|
46068
46411
|
function hashBundleFiles(files) {
|
|
46069
|
-
const hash2 =
|
|
46412
|
+
const hash2 = createHash26(CONTENT_HASH_ALGORITHM);
|
|
46070
46413
|
for (const part of bundleHashParts(files))
|
|
46071
46414
|
hash2.update(part);
|
|
46072
46415
|
return hash2.digest("hex");
|
|
46073
46416
|
}
|
|
46074
46417
|
async function hashBundleFilesCooperatively(files, check) {
|
|
46075
|
-
const hash2 =
|
|
46418
|
+
const hash2 = createHash26(CONTENT_HASH_ALGORITHM);
|
|
46076
46419
|
let bytesSinceYield = 0;
|
|
46077
46420
|
for (const part of bundleHashParts(files)) {
|
|
46078
46421
|
for (let offset = 0;offset < part.byteLength; offset += 64 * 1024) {
|
|
@@ -46081,7 +46424,7 @@ async function hashBundleFilesCooperatively(files, check) {
|
|
|
46081
46424
|
hash2.update(chunk);
|
|
46082
46425
|
bytesSinceYield += chunk.byteLength;
|
|
46083
46426
|
if (bytesSinceYield >= 256 * 1024) {
|
|
46084
|
-
await new Promise((
|
|
46427
|
+
await new Promise((resolve21) => setImmediate(resolve21));
|
|
46085
46428
|
bytesSinceYield = 0;
|
|
46086
46429
|
}
|
|
46087
46430
|
}
|
|
@@ -46204,8 +46547,8 @@ function boundedManifest(raw, maxDepth) {
|
|
|
46204
46547
|
continue;
|
|
46205
46548
|
if (depth > maxDepth)
|
|
46206
46549
|
contentLimit("Content hash manifest depth limit exceeded");
|
|
46207
|
-
for (const
|
|
46208
|
-
pending.push({ value:
|
|
46550
|
+
for (const child2 of Object.values(value))
|
|
46551
|
+
pending.push({ value: child2, depth: depth + 1 });
|
|
46209
46552
|
}
|
|
46210
46553
|
return parsed;
|
|
46211
46554
|
}
|
|
@@ -46234,7 +46577,7 @@ async function hashContentEntries(entries, options) {
|
|
|
46234
46577
|
const normalized = [];
|
|
46235
46578
|
let normalizedBytes = 0;
|
|
46236
46579
|
let manifest;
|
|
46237
|
-
await new Promise((
|
|
46580
|
+
await new Promise((resolve21) => setImmediate(resolve21));
|
|
46238
46581
|
for (const entry of snapshot2) {
|
|
46239
46582
|
check();
|
|
46240
46583
|
if (!coveredContentPath(entry.path))
|
|
@@ -46247,7 +46590,7 @@ async function hashContentEntries(entries, options) {
|
|
|
46247
46590
|
contentLimit("Content hash normalized byte limit exceeded");
|
|
46248
46591
|
normalizedBytes += file.content.byteLength;
|
|
46249
46592
|
normalized.push(file);
|
|
46250
|
-
await new Promise((
|
|
46593
|
+
await new Promise((resolve21) => setImmediate(resolve21));
|
|
46251
46594
|
}
|
|
46252
46595
|
normalized.sort((a, b) => a.rel < b.rel ? -1 : a.rel > b.rel ? 1 : 0);
|
|
46253
46596
|
check();
|
|
@@ -46461,7 +46804,7 @@ import {
|
|
|
46461
46804
|
realpathSync as realpathSync12,
|
|
46462
46805
|
writeFileSync as writeFileSync6
|
|
46463
46806
|
} from "fs";
|
|
46464
|
-
import { basename as
|
|
46807
|
+
import { basename as basename10, dirname as dirname19, join as join29, relative as relative6 } from "path";
|
|
46465
46808
|
var ANY_SEGMENT_COPY_EXCLUDES = new Set([
|
|
46466
46809
|
".git",
|
|
46467
46810
|
".DS_Store",
|
|
@@ -46511,11 +46854,11 @@ function normalizeNewPortableSkillName(name) {
|
|
|
46511
46854
|
throw new Error(`Invalid skill name '${name}'. Include letters or numbers.`);
|
|
46512
46855
|
return normalized;
|
|
46513
46856
|
}
|
|
46514
|
-
function readPortableSkillManifest(skillPath, fallbackName =
|
|
46857
|
+
function readPortableSkillManifest(skillPath, fallbackName = basename10(skillPath)) {
|
|
46515
46858
|
return readManifest(skillPath, fallbackName, normalizePortableSkillName);
|
|
46516
46859
|
}
|
|
46517
46860
|
function readPortableSkillManifestForImport(skillPath) {
|
|
46518
|
-
return readManifest(skillPath,
|
|
46861
|
+
return readManifest(skillPath, basename10(skillPath), normalizeNewPortableSkillName);
|
|
46519
46862
|
}
|
|
46520
46863
|
function readManifest(skillPath, fallbackName, normalizeName) {
|
|
46521
46864
|
const skillJsonPath = join29(skillPath, "skill.json");
|
|
@@ -46708,7 +47051,7 @@ function ensurePortableSkillFiles(skillPath, manifest) {
|
|
|
46708
47051
|
};
|
|
46709
47052
|
const entry = next.commands[0]?.entry ?? "src/index.ts";
|
|
46710
47053
|
if (entry && !existsSync9(join29(skillPath, entry))) {
|
|
46711
|
-
mkdirSync7(
|
|
47054
|
+
mkdirSync7(dirname19(join29(skillPath, entry)), { recursive: true });
|
|
46712
47055
|
writeFileSync6(join29(skillPath, entry), renderEntrypoint(next));
|
|
46713
47056
|
}
|
|
46714
47057
|
if (!existsSync9(join29(skillPath, "SKILL.md")))
|
|
@@ -47069,7 +47412,7 @@ function inferRuntimeFromCommands(commands) {
|
|
|
47069
47412
|
function readJsonObject(path) {
|
|
47070
47413
|
const parsed = JSON.parse(readFileSync19(path, "utf-8"));
|
|
47071
47414
|
if (!isRecord3(parsed))
|
|
47072
|
-
throw new Error(`${
|
|
47415
|
+
throw new Error(`${basename10(path)} must contain a JSON object`);
|
|
47073
47416
|
return parsed;
|
|
47074
47417
|
}
|
|
47075
47418
|
function hasPackageDependencies(pkgPath) {
|
|
@@ -47107,10 +47450,10 @@ function escapeJsString(value) {
|
|
|
47107
47450
|
// src/lib/authoring-path.ts
|
|
47108
47451
|
import { lstatSync as lstatSync25, realpathSync as realpathSync13 } from "fs";
|
|
47109
47452
|
import { homedir as homedir4 } from "os";
|
|
47110
|
-
import { basename as
|
|
47453
|
+
import { basename as basename11, dirname as dirname20, join as join30, resolve as resolve21, sep as sep9 } from "path";
|
|
47111
47454
|
var NATIVE_DISCOVERY_ROOTS = NATIVE_SKILL_ROOTS.map(([, path]) => path.split("/"));
|
|
47112
47455
|
function pathParts(path) {
|
|
47113
|
-
return
|
|
47456
|
+
return resolve21(path).split(sep9).filter(Boolean);
|
|
47114
47457
|
}
|
|
47115
47458
|
function nativeRootMatch(path) {
|
|
47116
47459
|
const parts = pathParts(path);
|
|
@@ -47124,16 +47467,16 @@ function nativeRootMatch(path) {
|
|
|
47124
47467
|
return;
|
|
47125
47468
|
}
|
|
47126
47469
|
function physicalPath(path) {
|
|
47127
|
-
let cursor =
|
|
47470
|
+
let cursor = resolve21(path);
|
|
47128
47471
|
const suffix = [];
|
|
47129
47472
|
while (!lstatSync25(cursor, { throwIfNoEntry: false })) {
|
|
47130
|
-
suffix.unshift(
|
|
47131
|
-
const parent =
|
|
47473
|
+
suffix.unshift(basename11(cursor));
|
|
47474
|
+
const parent = dirname20(cursor);
|
|
47132
47475
|
if (parent === cursor)
|
|
47133
|
-
return
|
|
47476
|
+
return resolve21(path);
|
|
47134
47477
|
cursor = parent;
|
|
47135
47478
|
}
|
|
47136
|
-
return
|
|
47479
|
+
return resolve21(realpathSync13(cursor), ...suffix);
|
|
47137
47480
|
}
|
|
47138
47481
|
function contains(root2, path) {
|
|
47139
47482
|
return path === root2 || path.startsWith(root2 + sep9);
|
|
@@ -47141,7 +47484,7 @@ function contains(root2, path) {
|
|
|
47141
47484
|
function configuredRoots(home, explicitHome) {
|
|
47142
47485
|
const homeData = join30(home, ".hasna", "skills");
|
|
47143
47486
|
const homePolicy = readManagedSkillPolicySnapshot(homeData);
|
|
47144
|
-
const configuredPolicy = !explicitHome &&
|
|
47487
|
+
const configuredPolicy = !explicitHome && resolve21(getDataDirReadOnly()) !== resolve21(homeData) ? readManagedSkillPolicySnapshot(getDataDirReadOnly()) : null;
|
|
47145
47488
|
const policy = homePolicy ?? configuredPolicy;
|
|
47146
47489
|
const bridge = policy?.value.bridge;
|
|
47147
47490
|
if (bridge && (typeof bridge.home !== "string" || physicalPath(bridge.home) !== physicalPath(home))) {
|
|
@@ -47180,22 +47523,22 @@ function configuredRoots(home, explicitHome) {
|
|
|
47180
47523
|
function assertPortableAuthoringPath(path, options = {}) {
|
|
47181
47524
|
if (typeof path !== "string" || !path || path.includes("\x00"))
|
|
47182
47525
|
throw new Error("Invalid portable authoring path");
|
|
47183
|
-
const lexical =
|
|
47526
|
+
const lexical = resolve21(path);
|
|
47184
47527
|
const physical = physicalPath(lexical);
|
|
47185
47528
|
const candidates = [lexical, physical];
|
|
47186
47529
|
let native = candidates.map(nativeRootMatch).find(Boolean);
|
|
47187
|
-
const home =
|
|
47530
|
+
const home = resolve21(options.homeDir ?? homedir4());
|
|
47188
47531
|
const defaults = NATIVE_DISCOVERY_ROOTS.map((parts) => join30(home, ...parts));
|
|
47189
47532
|
defaults.push(join30(home, ".codex/plugins/cache"), join30(home, ".claude/plugins/cache"), join30(home, ".claude/plugins/synced"), join30(home, ".gemini/extensions"));
|
|
47190
47533
|
for (const root2 of defaults) {
|
|
47191
|
-
if (candidates.some((candidate2) => contains(
|
|
47534
|
+
if (candidates.some((candidate2) => contains(resolve21(root2), candidate2) || contains(physicalPath(root2), candidate2)))
|
|
47192
47535
|
native ??= root2;
|
|
47193
47536
|
}
|
|
47194
47537
|
if (native) {
|
|
47195
47538
|
throw new Error(`Refusing portable Skills authoring below native discovery root '${native}': ${lexical}. Set HASNA_SKILLS_DIR to a private authoring corpus outside native roots.`);
|
|
47196
47539
|
}
|
|
47197
47540
|
for (const root2 of configuredRoots(home, options.homeDir !== undefined)) {
|
|
47198
|
-
if (candidates.some((candidate2) => contains(
|
|
47541
|
+
if (candidates.some((candidate2) => contains(resolve21(root2), candidate2) || contains(physicalPath(root2), candidate2))) {
|
|
47199
47542
|
throw new Error(`Refusing portable Skills authoring below configured native discovery root: ${lexical}`);
|
|
47200
47543
|
}
|
|
47201
47544
|
}
|
|
@@ -47343,20 +47686,20 @@ function isSkillCandidate(dir) {
|
|
|
47343
47686
|
return existsSync10(join31(dir, "SKILL.md")) || existsSync10(join31(dir, "skill.json")) || existsSync10(join31(dir, "package.json"));
|
|
47344
47687
|
}
|
|
47345
47688
|
function physicalImportPath(path) {
|
|
47346
|
-
let ancestor =
|
|
47689
|
+
let ancestor = resolve22(path);
|
|
47347
47690
|
const suffix = [];
|
|
47348
47691
|
while (!existsSync10(ancestor)) {
|
|
47349
|
-
suffix.unshift(
|
|
47350
|
-
ancestor =
|
|
47692
|
+
suffix.unshift(basename12(ancestor));
|
|
47693
|
+
ancestor = dirname21(ancestor);
|
|
47351
47694
|
}
|
|
47352
47695
|
return join31(realpathSync14(ancestor), ...suffix);
|
|
47353
47696
|
}
|
|
47354
47697
|
function assertDisjointImportPaths(source, destination) {
|
|
47355
47698
|
const sourcePath = realpathSync14(source);
|
|
47356
47699
|
const destinationPath = physicalImportPath(destination);
|
|
47357
|
-
const contains2 = (parent,
|
|
47358
|
-
const path = relative7(parent,
|
|
47359
|
-
return path === "" || !
|
|
47700
|
+
const contains2 = (parent, child2) => {
|
|
47701
|
+
const path = relative7(parent, child2);
|
|
47702
|
+
return path === "" || !isAbsolute23(path) && path !== ".." && !path.startsWith(`..${sep10}`);
|
|
47360
47703
|
};
|
|
47361
47704
|
if (contains2(sourcePath, destinationPath) || contains2(destinationPath, sourcePath)) {
|
|
47362
47705
|
throw new Error("Source and destination skill directories must not overlap");
|
|
@@ -47371,8 +47714,8 @@ function portPortableSkill(sourcePath, options = {}) {
|
|
|
47371
47714
|
const explicitName = options.name != null;
|
|
47372
47715
|
const skillName = normalizeNewPortableSkillName(options.name ?? inferred.name);
|
|
47373
47716
|
if (isOfficialSkillName(skillName) && !options.allowShadow) {
|
|
47374
|
-
const sourceSlug = safeNormalizeName(
|
|
47375
|
-
const via = explicitName ? `Name '${skillName}' matches a bundled official skill.` : `Inferred name '${skillName}'${sourceSlug && sourceSlug !== skillName ? ` (from source folder '${
|
|
47717
|
+
const sourceSlug = safeNormalizeName(basename12(absoluteSource));
|
|
47718
|
+
const via = explicitName ? `Name '${skillName}' matches a bundled official skill.` : `Inferred name '${skillName}'${sourceSlug && sourceSlug !== skillName ? ` (from source folder '${basename12(absoluteSource)}')` : ""} matches a bundled official skill.`;
|
|
47376
47719
|
throw new Error(`${via} Importing it would shadow the official '${skillName}'. ` + `Pass --name to choose a different name, or --allow-shadow to override deliberately.`);
|
|
47377
47720
|
}
|
|
47378
47721
|
const readOnlyDestination = join31(resolvePortableSkillsRoot(options, false), skillName);
|
|
@@ -47387,7 +47730,7 @@ function portPortableSkill(sourcePath, options = {}) {
|
|
|
47387
47730
|
throw new Error(`Skill '${skillName}' already exists at ${destination}`);
|
|
47388
47731
|
rmSync2(destination, { recursive: true, force: true });
|
|
47389
47732
|
}
|
|
47390
|
-
mkdirSync8(
|
|
47733
|
+
mkdirSync8(dirname21(destination), { recursive: true });
|
|
47391
47734
|
copySkillDirectory(absoluteSource, destination);
|
|
47392
47735
|
const base = {
|
|
47393
47736
|
...inferred,
|
|
@@ -47637,7 +47980,7 @@ function safeIsDirectory(path) {
|
|
|
47637
47980
|
}
|
|
47638
47981
|
}
|
|
47639
47982
|
function isSafeRelativePath2(value) {
|
|
47640
|
-
if (!value.trim() ||
|
|
47983
|
+
if (!value.trim() || isAbsolute23(value))
|
|
47641
47984
|
return false;
|
|
47642
47985
|
const normalized = normalize4(value).replace(/\\/g, "/");
|
|
47643
47986
|
return normalized !== ".." && !normalized.startsWith("../") && !normalized.includes("/../");
|
|
@@ -47898,9 +48241,9 @@ function writeManagedSkillDirUnlocked(dir, skillMd, options, assertCurrent) {
|
|
|
47898
48241
|
const action = dirExists ? "update" : "create";
|
|
47899
48242
|
if (options.dryRun)
|
|
47900
48243
|
return { action, path: skillMdPath };
|
|
47901
|
-
const parentDir =
|
|
48244
|
+
const parentDir = dirname22(dir);
|
|
47902
48245
|
mkdirSync9(parentDir, { recursive: true });
|
|
47903
|
-
const transactionDir = mkdtempSync2(join32(parentDir, `.hasna-skills-write-${
|
|
48246
|
+
const transactionDir = mkdtempSync2(join32(parentDir, `.hasna-skills-write-${basename13(dir)}-`));
|
|
47904
48247
|
const candidateDir = join32(transactionDir, "candidate");
|
|
47905
48248
|
const backupDir = join32(transactionDir, "backup");
|
|
47906
48249
|
const candidateSkillMdPath = join32(candidateDir, "SKILL.md");
|
|
@@ -49287,11 +49630,11 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
49287
49630
|
throw new SkillSelectionError("INVALID_BUNDLE_PATH", "The execution bundle path exceeds its limit.");
|
|
49288
49631
|
});
|
|
49289
49632
|
const destination = join37(runDirectory, entry.path);
|
|
49290
|
-
mkdirSync11(
|
|
49633
|
+
mkdirSync11(dirname23(destination), { recursive: true, mode: 448 });
|
|
49291
49634
|
writeFileSync10(destination, entry.bytes, { flag: "wx", mode: entry.mode & 511 });
|
|
49292
49635
|
}
|
|
49293
49636
|
env.SKILLS_INPUT_JSON = input;
|
|
49294
|
-
env.SKILLS_WORKSPACE_DIR =
|
|
49637
|
+
env.SKILLS_WORKSPACE_DIR = resolve23(options.cwd ?? process.cwd());
|
|
49295
49638
|
env.SKILLS_RUN_DIR = runDirectory;
|
|
49296
49639
|
if (runtime.version) {
|
|
49297
49640
|
const version = await subprocess([executable2, ...runtimeName === "bun" ? ["--no-env-file"] : [], "--version"], runDirectory, env, "", Math.min(timeoutMs, 5000));
|
|
@@ -49321,7 +49664,7 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
49321
49664
|
selection: selection2,
|
|
49322
49665
|
target: "local",
|
|
49323
49666
|
runtime: runtimeName,
|
|
49324
|
-
inputDigest: `sha256:${
|
|
49667
|
+
inputDigest: `sha256:${createHash27("sha256").update(input).digest("hex")}`,
|
|
49325
49668
|
runDirectory,
|
|
49326
49669
|
...executionGrant ? { executionGrant } : {},
|
|
49327
49670
|
...bindings ? { secretBinding: { schema: bindings.schema, selection: bindings.selection, consumer: bindings.consumer, secretsAuthority: bindings.secretsAuthority, bindings: bindings.bindings } } : {},
|
|
@@ -49332,17 +49675,17 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
49332
49675
|
}
|
|
49333
49676
|
async function subprocess(command, cwd, env, input, timeoutMs) {
|
|
49334
49677
|
return new Promise((resolveResult) => {
|
|
49335
|
-
const
|
|
49678
|
+
const child2 = spawn2(command[0], command.slice(1), { cwd, env, shell: false, detached: process.platform !== "win32", stdio: ["pipe", "pipe", "pipe"] });
|
|
49336
49679
|
let outputBytes = 0, error, ended = false;
|
|
49337
49680
|
const stdout = [], stderr = [];
|
|
49338
49681
|
const kill = () => {
|
|
49339
49682
|
try {
|
|
49340
|
-
if (process.platform !== "win32" &&
|
|
49341
|
-
process.kill(-
|
|
49683
|
+
if (process.platform !== "win32" && child2.pid)
|
|
49684
|
+
process.kill(-child2.pid, "SIGKILL");
|
|
49342
49685
|
else
|
|
49343
|
-
|
|
49686
|
+
child2.kill("SIGKILL");
|
|
49344
49687
|
} catch {
|
|
49345
|
-
|
|
49688
|
+
child2.kill("SIGKILL");
|
|
49346
49689
|
}
|
|
49347
49690
|
};
|
|
49348
49691
|
const timer = setTimeout(() => {
|
|
@@ -49358,8 +49701,8 @@ async function subprocess(command, cwd, env, input, timeoutMs) {
|
|
|
49358
49701
|
}
|
|
49359
49702
|
target.push(chunk);
|
|
49360
49703
|
};
|
|
49361
|
-
|
|
49362
|
-
|
|
49704
|
+
child2.stdout.on("data", capture2(stdout));
|
|
49705
|
+
child2.stderr.on("data", capture2(stderr));
|
|
49363
49706
|
const finish = (code) => {
|
|
49364
49707
|
if (ended)
|
|
49365
49708
|
return;
|
|
@@ -49367,13 +49710,13 @@ async function subprocess(command, cwd, env, input, timeoutMs) {
|
|
|
49367
49710
|
clearTimeout(timer);
|
|
49368
49711
|
resolveResult({ exitCode: error === "LOCAL_RUN_TIMEOUT" ? 124 : error ? 1 : code, stdout: Buffer.concat(stdout).toString("utf8"), stderr: Buffer.concat(stderr).toString("utf8"), ...error ? { error } : {} });
|
|
49369
49712
|
};
|
|
49370
|
-
|
|
49713
|
+
child2.on("error", () => {
|
|
49371
49714
|
error = "LOCAL_RUNTIME_START_FAILED";
|
|
49372
49715
|
finish(127);
|
|
49373
49716
|
});
|
|
49374
|
-
|
|
49375
|
-
|
|
49376
|
-
|
|
49717
|
+
child2.on("close", (code) => finish(code ?? 1));
|
|
49718
|
+
child2.stdin.on("error", () => {});
|
|
49719
|
+
child2.stdin.end(input);
|
|
49377
49720
|
});
|
|
49378
49721
|
}
|
|
49379
49722
|
// src/lib/remote-run-contract.ts
|
|
@@ -58611,7 +58954,7 @@ var import_node_http_handler2 = __toESM(require_dist_cjs6(), 1);
|
|
|
58611
58954
|
|
|
58612
58955
|
// node_modules/@aws-sdk/checksums/dist-cjs/submodules/sha/index.js
|
|
58613
58956
|
var { toUint8Array: toUint8Array2, concatBytes } = require_serde();
|
|
58614
|
-
var { createHmac: createHmac2, createHash:
|
|
58957
|
+
var { createHmac: createHmac2, createHash: createHash29 } = __require("crypto");
|
|
58615
58958
|
var { Sha256: Sha2562, Sha256Js, Sha256Node } = require_checksum();
|
|
58616
58959
|
var BLOCK2 = 64;
|
|
58617
58960
|
var DIGEST_LENGTH = 20;
|
|
@@ -58780,7 +59123,7 @@ class Sha1Js {
|
|
|
58780
59123
|
}
|
|
58781
59124
|
var hasNativeCrypto = (() => {
|
|
58782
59125
|
try {
|
|
58783
|
-
|
|
59126
|
+
createHash29("sha1");
|
|
58784
59127
|
return true;
|
|
58785
59128
|
} catch {
|
|
58786
59129
|
return false;
|
|
@@ -58820,7 +59163,7 @@ function buildNativeClass() {
|
|
|
58820
59163
|
this.finished = false;
|
|
58821
59164
|
}
|
|
58822
59165
|
createHash() {
|
|
58823
|
-
return this.secret ? createHmac2("sha1", toBuffer(this.secret)) :
|
|
59166
|
+
return this.secret ? createHmac2("sha1", toBuffer(this.secret)) : createHash29("sha1");
|
|
58824
59167
|
}
|
|
58825
59168
|
};
|
|
58826
59169
|
}
|
|
@@ -59373,15 +59716,15 @@ function createCancelService(options) {
|
|
|
59373
59716
|
}
|
|
59374
59717
|
|
|
59375
59718
|
// src/sdk/amounts.ts
|
|
59376
|
-
function assertCents(value,
|
|
59719
|
+
function assertCents(value, field3) {
|
|
59377
59720
|
if (!Number.isSafeInteger(value) || value < 0) {
|
|
59378
|
-
throw new RangeError(
|
|
59721
|
+
throw new RangeError(field3 + " must be a nonnegative safe integer number of cents");
|
|
59379
59722
|
}
|
|
59380
59723
|
}
|
|
59381
|
-
function assertReservationCents(value,
|
|
59382
|
-
assertCents(value,
|
|
59724
|
+
function assertReservationCents(value, field3) {
|
|
59725
|
+
assertCents(value, field3);
|
|
59383
59726
|
if (value > 2147483647) {
|
|
59384
|
-
throw new RangeError(
|
|
59727
|
+
throw new RangeError(field3 + " must not exceed 2147483647 cents per reservation");
|
|
59385
59728
|
}
|
|
59386
59729
|
}
|
|
59387
59730
|
|
|
@@ -59389,10 +59732,10 @@ function assertReservationCents(value, field2) {
|
|
|
59389
59732
|
import { Database as Database2 } from "bun:sqlite";
|
|
59390
59733
|
import { randomUUID as randomUUID9 } from "crypto";
|
|
59391
59734
|
import { mkdirSync as mkdirSync13 } from "fs";
|
|
59392
|
-
import { dirname as
|
|
59735
|
+
import { dirname as dirname27 } from "path";
|
|
59393
59736
|
|
|
59394
59737
|
// src/server/database-url.ts
|
|
59395
|
-
import { isAbsolute as
|
|
59738
|
+
import { isAbsolute as isAbsolute24, join as join39 } from "path";
|
|
59396
59739
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
59397
59740
|
var DEFAULT_SQLITE_FILENAME2 = "server.db";
|
|
59398
59741
|
var SQLITE_MEMORY_PATH = ":memory:";
|
|
@@ -59428,7 +59771,7 @@ function resolveDatabaseTarget(raw) {
|
|
|
59428
59771
|
throw new Error(`unsupported database scheme "${scheme}:". Supported: postgres://, postgresql://, sqlite:, file:, ` + `an absolute or relative path to a .db/.sqlite file, ":memory:", or "memory:" (non-durable, tests only). ` + `Leave the setting empty to use the default SQLite database at ${defaultSqlitePath()}.`);
|
|
59429
59772
|
}
|
|
59430
59773
|
if (looksLikeSqlitePath(value)) {
|
|
59431
|
-
const path =
|
|
59774
|
+
const path = isAbsolute24(value) ? value : join39(process.cwd(), value);
|
|
59432
59775
|
return { kind: "sqlite", path, durable: true, label: `sqlite (${path})` };
|
|
59433
59776
|
}
|
|
59434
59777
|
throw new Error(`could not resolve a database backend from "${value}". Use postgres://\u2026, sqlite:\u2026, an absolute or ` + `relative path ending in ${SQLITE_EXTENSIONS.join("/")}, ":memory:", or leave it empty for the ` + `default SQLite database at ${defaultSqlitePath()}.`);
|
|
@@ -59452,7 +59795,7 @@ function sqlitePathFromUrl(value, scheme) {
|
|
|
59452
59795
|
}
|
|
59453
59796
|
return rest.slice(2).replace(/^\/\/+/, "/");
|
|
59454
59797
|
}
|
|
59455
|
-
return
|
|
59798
|
+
return isAbsolute24(rest) ? rest : join39(process.cwd(), rest);
|
|
59456
59799
|
}
|
|
59457
59800
|
function looksLikeSqlitePath(value) {
|
|
59458
59801
|
if (value.includes("/"))
|
|
@@ -59685,12 +60028,12 @@ class PostgresSkillSelectionStore {
|
|
|
59685
60028
|
// src/server/sqlite-store.ts
|
|
59686
60029
|
import { randomUUID as randomUUID8 } from "crypto";
|
|
59687
60030
|
import { mkdirSync as mkdirSync12, readFileSync as readFileSync26, readdirSync as readdirSync13 } from "fs";
|
|
59688
|
-
import { dirname as
|
|
60031
|
+
import { dirname as dirname26, join as join41 } from "path";
|
|
59689
60032
|
|
|
59690
60033
|
// src/server/auth.ts
|
|
59691
|
-
import { createHash as
|
|
60034
|
+
import { createHash as createHash30 } from "crypto";
|
|
59692
60035
|
function hashApiKey(token) {
|
|
59693
|
-
return
|
|
60036
|
+
return createHash30("sha256").update(token).digest("hex");
|
|
59694
60037
|
}
|
|
59695
60038
|
function bearerToken(request2) {
|
|
59696
60039
|
const header = request2.headers.get("authorization") || "";
|
|
@@ -59744,7 +60087,7 @@ function permitsSkillsRoute(principal, method, resource) {
|
|
|
59744
60087
|
|
|
59745
60088
|
// src/server/migrations-dir.ts
|
|
59746
60089
|
import { existsSync as existsSync16 } from "fs";
|
|
59747
|
-
import { dirname as
|
|
60090
|
+
import { dirname as dirname25, join as join40 } from "path";
|
|
59748
60091
|
var MIGRATION_DIALECTS = ["postgres", "sqlite"];
|
|
59749
60092
|
var MAX_WALK_UP = 6;
|
|
59750
60093
|
function findMigrationsRoot(startDirs = defaultStartDirs()) {
|
|
@@ -59754,7 +60097,7 @@ function findMigrationsRoot(startDirs = defaultStartDirs()) {
|
|
|
59754
60097
|
const candidate2 = join40(dir, "migrations");
|
|
59755
60098
|
if (MIGRATION_DIALECTS.some((dialect) => existsSync16(join40(candidate2, dialect))))
|
|
59756
60099
|
return candidate2;
|
|
59757
|
-
const parent =
|
|
60100
|
+
const parent = dirname25(dir);
|
|
59758
60101
|
if (parent === dir)
|
|
59759
60102
|
break;
|
|
59760
60103
|
dir = parent;
|
|
@@ -60009,12 +60352,12 @@ class SkillLifecycleConflictError extends Error {
|
|
|
60009
60352
|
}
|
|
60010
60353
|
}
|
|
60011
60354
|
function validOperatorScopeEnrollmentInput(input) {
|
|
60012
|
-
const
|
|
60013
|
-
return
|
|
60355
|
+
const bounded2 = (value, max = 256) => typeof value === "string" && value.length > 0 && value.length <= max && !/[\u0000-\u001f\u007f]/.test(value);
|
|
60356
|
+
return bounded2(input.keyId) && bounded2(input.stationId) && bounded2(input.orgId) && bounded2(input.operationId) && bounded2(input.manifestDigest, 64) && /^[a-f0-9]{64}$/.test(input.manifestDigest) && bounded2(input.operatorJobId) && bounded2(input.operatorTaskArn, 512) && input.expectedScopes.length > 0 && input.expectedScopes.length <= 32 && input.expectedScopes.every((scope) => bounded2(scope, 128) && /^[a-z][a-z0-9_-]*:[a-z][a-z0-9_-]*$/.test(scope));
|
|
60014
60357
|
}
|
|
60015
60358
|
|
|
60016
60359
|
// src/lib/revision.ts
|
|
60017
|
-
import { createHash as
|
|
60360
|
+
import { createHash as createHash31 } from "crypto";
|
|
60018
60361
|
var REVISION_ID_PATTERN = /^[0-9a-f]{64}$/;
|
|
60019
60362
|
function revisionIdOf(content) {
|
|
60020
60363
|
const canonicalContent = {
|
|
@@ -60035,8 +60378,8 @@ function revisionIdOf(content) {
|
|
|
60035
60378
|
canonicalContent.archiveReason = content.archiveReason ?? null;
|
|
60036
60379
|
canonicalContent.replacementSlug = content.replacementSlug ?? null;
|
|
60037
60380
|
}
|
|
60038
|
-
const
|
|
60039
|
-
return
|
|
60381
|
+
const canonical8 = JSON.stringify(canonicalContent);
|
|
60382
|
+
return createHash31("sha256").update(canonical8).digest("hex");
|
|
60040
60383
|
}
|
|
60041
60384
|
function revisionIdOfRecord(record4) {
|
|
60042
60385
|
return revisionIdOf(record4);
|
|
@@ -60061,7 +60404,7 @@ class SqliteSkillsStore {
|
|
|
60061
60404
|
constructor(path = SQLITE_MEMORY_PATH, options = {}) {
|
|
60062
60405
|
const inMemory = path === SQLITE_MEMORY_PATH;
|
|
60063
60406
|
if (!inMemory)
|
|
60064
|
-
mkdirSync12(
|
|
60407
|
+
mkdirSync12(dirname26(path), { recursive: true });
|
|
60065
60408
|
this.db = openDatabase(path);
|
|
60066
60409
|
this.db.exec(`PRAGMA busy_timeout = ${Math.max(0, options.busyTimeoutMs ?? 5000)}`);
|
|
60067
60410
|
if (!inMemory)
|
|
@@ -60778,8 +61121,8 @@ function openDatabase(path) {
|
|
|
60778
61121
|
try {
|
|
60779
61122
|
return new Database(path, { create: true, readwrite: true });
|
|
60780
61123
|
} catch (error) {
|
|
60781
|
-
const
|
|
60782
|
-
throw new Error(`cannot open the skills database at ${path}: ${
|
|
61124
|
+
const reason2 = error instanceof Error ? error.message : String(error);
|
|
61125
|
+
throw new Error(`cannot open the skills database at ${path}: ${reason2}. ` + "Check that the directory exists and is writable. Set HASNA_SKILLS_DATABASE_URL to choose a " + "different path or a postgres:// URL, or HASNA_SKILLS_DIR to relocate the whole data directory.", { cause: error });
|
|
60783
61126
|
}
|
|
60784
61127
|
}
|
|
60785
61128
|
function parseScopes(value) {
|
|
@@ -60887,7 +61230,7 @@ class SqliteGovernanceStore {
|
|
|
60887
61230
|
closed = false;
|
|
60888
61231
|
constructor(path = SQLITE_MEMORY_PATH, options = {}) {
|
|
60889
61232
|
if (path !== SQLITE_MEMORY_PATH)
|
|
60890
|
-
mkdirSync13(
|
|
61233
|
+
mkdirSync13(dirname27(path), { recursive: true });
|
|
60891
61234
|
this.db = new Database2(path, { create: true, readwrite: true });
|
|
60892
61235
|
this.db.exec("PRAGMA busy_timeout = 5000");
|
|
60893
61236
|
this.db.exec("PRAGMA foreign_keys = ON");
|
|
@@ -61120,7 +61463,7 @@ function nextMonthPrefix(monthPrefix) {
|
|
|
61120
61463
|
}
|
|
61121
61464
|
|
|
61122
61465
|
// src/server/skills-api.ts
|
|
61123
|
-
import { createHash as
|
|
61466
|
+
import { createHash as createHash32 } from "crypto";
|
|
61124
61467
|
var SLUG_PATTERN = /^[a-z0-9][a-z0-9._-]*$/;
|
|
61125
61468
|
var SHA256_HEX2 = /^[0-9a-f]{64}$/;
|
|
61126
61469
|
var MAX_SLUG_LENGTH = 128;
|
|
@@ -61310,7 +61653,7 @@ async function parsePublishRequest(request2, config) {
|
|
|
61310
61653
|
if (bundleBytes.byteLength === 0) {
|
|
61311
61654
|
throw new SkillRequestError(400, "BUNDLE_EMPTY", "the uploaded bundle is empty");
|
|
61312
61655
|
}
|
|
61313
|
-
const sha2563 =
|
|
61656
|
+
const sha2563 = createHash32("sha256").update(bundleBytes).digest("hex");
|
|
61314
61657
|
const claimed = optionalString(manifest.bundleSha256);
|
|
61315
61658
|
if (claimed)
|
|
61316
61659
|
assertSha2562(claimed);
|
|
@@ -61425,7 +61768,7 @@ async function readPublishedBundle(store, artifactStorage, principal, slug) {
|
|
|
61425
61768
|
if (!bytes) {
|
|
61426
61769
|
throw new SkillRequestError(503, "BUNDLE_BACKEND_UNAVAILABLE", "bundle storage backend unavailable");
|
|
61427
61770
|
}
|
|
61428
|
-
const actual =
|
|
61771
|
+
const actual = createHash32("sha256").update(bytes).digest("hex");
|
|
61429
61772
|
if (actual !== record4.bundleSha256) {
|
|
61430
61773
|
throw new SkillRequestError(500, "BUNDLE_DIGEST_DRIFT", `stored bundle for '${slug}' hashes to ${actual} but was published as ${record4.bundleSha256}`);
|
|
61431
61774
|
}
|
|
@@ -61482,7 +61825,7 @@ function buildPublishInput(manifest) {
|
|
|
61482
61825
|
displayName: optionalString(manifest.displayName) ?? titleize(slug),
|
|
61483
61826
|
description,
|
|
61484
61827
|
category: optionalString(manifest.category) ?? "Development Tools",
|
|
61485
|
-
tags:
|
|
61828
|
+
tags: stringArray2(manifest.tags),
|
|
61486
61829
|
source: publishSource(optionalString(manifest.source)),
|
|
61487
61830
|
kind: kindValue,
|
|
61488
61831
|
...publishVersionOf(manifest) ? { version: publishVersionOf(manifest) } : {},
|
|
@@ -61511,7 +61854,7 @@ function optionalString(value) {
|
|
|
61511
61854
|
function optionalText(value) {
|
|
61512
61855
|
return typeof value === "string" && value.trim() ? value : undefined;
|
|
61513
61856
|
}
|
|
61514
|
-
function
|
|
61857
|
+
function stringArray2(value) {
|
|
61515
61858
|
if (!Array.isArray(value))
|
|
61516
61859
|
return [];
|
|
61517
61860
|
return value.filter((item) => typeof item === "string" && item.trim().length > 0).map((item) => item.trim());
|
|
@@ -61573,7 +61916,7 @@ async function readSkillVersionBundle(store, artifactStorage, principal, slug, v
|
|
|
61573
61916
|
const bytes = await artifactStorage.readBundle(bundle2);
|
|
61574
61917
|
if (!bytes)
|
|
61575
61918
|
throw new SkillRequestError(503, "BUNDLE_BACKEND_UNAVAILABLE", "bundle storage backend unavailable");
|
|
61576
|
-
const actual =
|
|
61919
|
+
const actual = createHash32("sha256").update(bytes).digest("hex");
|
|
61577
61920
|
if (actual !== found.bundleSha256) {
|
|
61578
61921
|
throw new SkillRequestError(500, "BUNDLE_DIGEST_DRIFT", `stored bundle for '${slug}@${version2}' hashes to ${actual} but was published as ${found.bundleSha256}`);
|
|
61579
61922
|
}
|
|
@@ -61656,7 +61999,7 @@ async function validatePublishedGrant(store, artifacts, principal, grant) {
|
|
|
61656
61999
|
invalid3();
|
|
61657
62000
|
}
|
|
61658
62001
|
async function handleExecutionGrantApi(store, principal, request2, parts, config, artifacts) {
|
|
61659
|
-
const [resource, id2,
|
|
62002
|
+
const [resource, id2, child2, revision] = parts;
|
|
61660
62003
|
if (resource !== "execution-grants")
|
|
61661
62004
|
return null;
|
|
61662
62005
|
if (!grantIdentifier(id2))
|
|
@@ -61664,7 +62007,7 @@ async function handleExecutionGrantApi(store, principal, request2, parts, config
|
|
|
61664
62007
|
const { executionGrantStore: policies, selectionStore: profiles } = store;
|
|
61665
62008
|
if (!policies || !profiles)
|
|
61666
62009
|
refuse5(503, "EXECUTION_GRANTS_UNAVAILABLE", "This store does not support execution grants.");
|
|
61667
|
-
const historical = parts.length === 4 &&
|
|
62010
|
+
const historical = parts.length === 4 && child2 === "versions" && grantIdentifier(revision);
|
|
61668
62011
|
if (request2.method === "GET" && (parts.length === 2 || historical)) {
|
|
61669
62012
|
const policy = await policies.get(principal, id2, historical ? revision : undefined);
|
|
61670
62013
|
if (!policy)
|
|
@@ -61703,7 +62046,7 @@ async function handleExecutionGrantApi(store, principal, request2, parts, config
|
|
|
61703
62046
|
refuse5(409, "EXECUTION_GRANT_REVISION_CONFLICT", "Execution grant policy changed; read it before retrying.");
|
|
61704
62047
|
return json(saved, create ? 201 : 200, saved.revision);
|
|
61705
62048
|
}
|
|
61706
|
-
if (request2.method === "POST" && parts.length === 3 &&
|
|
62049
|
+
if (request2.method === "POST" && parts.length === 3 && child2 === "resolve") {
|
|
61707
62050
|
const input = await body(request2, Math.min(config.requestBodyLimitBytes, 16384));
|
|
61708
62051
|
let consumer;
|
|
61709
62052
|
try {
|
|
@@ -61868,7 +62211,7 @@ function json2(value, status = 200, revision) {
|
|
|
61868
62211
|
});
|
|
61869
62212
|
}
|
|
61870
62213
|
async function handleProfileApi(store, principal, request2, parts, config) {
|
|
61871
|
-
const [resource, id2,
|
|
62214
|
+
const [resource, id2, child2] = parts;
|
|
61872
62215
|
if (resource === "capabilities" && request2.method === "GET" && parts.length === 1)
|
|
61873
62216
|
return json2({
|
|
61874
62217
|
contractVersion: 1,
|
|
@@ -61934,13 +62277,13 @@ async function handleProfileApi(store, principal, request2, parts, config) {
|
|
|
61934
62277
|
throw new SkillRequestError(409, "PROFILE_REVISION_CONFLICT", "Profile changed; read it before retrying");
|
|
61935
62278
|
return json2(saved, create ? 201 : 200, saved.revision);
|
|
61936
62279
|
}
|
|
61937
|
-
if (resource === "profiles" && request2.method === "GET" && (parts.length === 2 || parts.length === 3 &&
|
|
62280
|
+
if (resource === "profiles" && request2.method === "GET" && (parts.length === 2 || parts.length === 3 && child2 === "resolve")) {
|
|
61938
62281
|
const profile2 = await adapter.getProfile(principal, id2);
|
|
61939
62282
|
if (!profile2)
|
|
61940
62283
|
throw new SkillRequestError(404, "PROFILE_NOT_FOUND", "Profile not found");
|
|
61941
62284
|
if (profile2.selections.length > MAX_PROFILE_SELECTIONS)
|
|
61942
62285
|
throw new SkillRequestError(413, "PROFILE_TOO_LARGE", "Profile exceeds the advertised selection limit");
|
|
61943
|
-
if (!
|
|
62286
|
+
if (!child2)
|
|
61944
62287
|
return json2(profile2, 200, profile2.revision);
|
|
61945
62288
|
const authority2 = skillsApiRequestUrl(normalizeSkillsApiOrigin(config.publicBaseUrl), "/api/v1/").replace(/\/+$/, "");
|
|
61946
62289
|
const result = resolvedProfileSnapshot(profile2, authority2);
|
|
@@ -61959,7 +62302,7 @@ async function handleProfileApi(store, principal, request2, parts, config) {
|
|
|
61959
62302
|
throw new SkillRequestError(413, "PROFILE_TOO_LARGE", "Resolved profile exceeds the advertised profile limits");
|
|
61960
62303
|
return json2(result, 200, profile2.revision);
|
|
61961
62304
|
}
|
|
61962
|
-
if (resource === "stations" && parts.length === 3 &&
|
|
62305
|
+
if (resource === "stations" && parts.length === 3 && child2 === "state") {
|
|
61963
62306
|
if (request2.method === "GET") {
|
|
61964
62307
|
const state2 = await adapter.getStationState(principal, id2);
|
|
61965
62308
|
if (!state2)
|
|
@@ -61993,7 +62336,7 @@ async function handleProfileApi(store, principal, request2, parts, config) {
|
|
|
61993
62336
|
// src/server/runtime-store.ts
|
|
61994
62337
|
import { Database as Database3 } from "bun:sqlite";
|
|
61995
62338
|
import { mkdirSync as mkdirSync14 } from "fs";
|
|
61996
|
-
import { dirname as
|
|
62339
|
+
import { dirname as dirname28 } from "path";
|
|
61997
62340
|
|
|
61998
62341
|
// src/sdk/execution/types.ts
|
|
61999
62342
|
var EXECUTION_PROTOCOL_VERSION = REMOTE_SKILL_RUN_CONTRACT_VERSION;
|
|
@@ -62049,7 +62392,7 @@ class RuntimeExecutionStore {
|
|
|
62049
62392
|
}
|
|
62050
62393
|
const path = target.kind === "sqlite" ? target.path : ":memory:";
|
|
62051
62394
|
if (path !== ":memory:")
|
|
62052
|
-
mkdirSync14(
|
|
62395
|
+
mkdirSync14(dirname28(path), { recursive: true });
|
|
62053
62396
|
const db = new Database3(path);
|
|
62054
62397
|
db.run("PRAGMA busy_timeout=5000");
|
|
62055
62398
|
db.run("PRAGMA journal_mode=WAL");
|
|
@@ -62289,7 +62632,7 @@ class RuntimeExecutionStore {
|
|
|
62289
62632
|
}
|
|
62290
62633
|
|
|
62291
62634
|
// src/sdk/execution/admission.ts
|
|
62292
|
-
import { createHash as
|
|
62635
|
+
import { createHash as createHash34 } from "crypto";
|
|
62293
62636
|
|
|
62294
62637
|
// src/sdk/execution/image-profile.ts
|
|
62295
62638
|
class ImageProfileResolutionError extends Error {
|
|
@@ -62901,11 +63244,11 @@ function ownedAdmission(admission) {
|
|
|
62901
63244
|
};
|
|
62902
63245
|
}
|
|
62903
63246
|
function digestInput(input) {
|
|
62904
|
-
return
|
|
63247
|
+
return createHash34("sha256").update(canonicalJson2(input)).digest("hex");
|
|
62905
63248
|
}
|
|
62906
63249
|
|
|
62907
63250
|
// src/sdk/execution/dispatchers/ecs.ts
|
|
62908
|
-
import { createHash as
|
|
63251
|
+
import { createHash as createHash35 } from "crypto";
|
|
62909
63252
|
|
|
62910
63253
|
// src/sdk/execution/state-machine.ts
|
|
62911
63254
|
var LEGAL_TRANSITIONS = {
|
|
@@ -66305,13 +66648,13 @@ function observedTask(states, taskArn) {
|
|
|
66305
66648
|
return state2.lastStatus === "STOPPED" || LIVE_TASK_STATUSES.has(state2.lastStatus) ? state2 : undefined;
|
|
66306
66649
|
}
|
|
66307
66650
|
function clientTokenFor(runId3, attemptId) {
|
|
66308
|
-
return
|
|
66651
|
+
return createHash35("sha256").update(`${runId3}\x00${attemptId}`).digest("hex").slice(0, CLIENT_TOKEN_BYTES * 2);
|
|
66309
66652
|
}
|
|
66310
66653
|
function startedByFor(runId3, attemptNumber) {
|
|
66311
66654
|
return `skills-exec/${runId3}/a${attemptNumber}`;
|
|
66312
66655
|
}
|
|
66313
66656
|
function requestDigestFor(admission, attemptId) {
|
|
66314
|
-
return
|
|
66657
|
+
return createHash35("sha256").update(canonicalJson2({ admission, attemptId })).digest("hex");
|
|
66315
66658
|
}
|
|
66316
66659
|
|
|
66317
66660
|
class EcsDispatcher {
|
|
@@ -66607,10 +66950,10 @@ function validText(value) {
|
|
|
66607
66950
|
}
|
|
66608
66951
|
|
|
66609
66952
|
// src/server/runtime-policy.ts
|
|
66610
|
-
import { createHash as
|
|
66953
|
+
import { createHash as createHash37, createHmac as createHmac3, timingSafeEqual as timingSafeEqual2 } from "crypto";
|
|
66611
66954
|
|
|
66612
66955
|
// src/server/runtime-pure-contract.ts
|
|
66613
|
-
import { createHash as
|
|
66956
|
+
import { createHash as createHash36 } from "crypto";
|
|
66614
66957
|
var PURE_DESCRIPTOR = Object.freeze({
|
|
66615
66958
|
id: "regex-test.v1",
|
|
66616
66959
|
runtime: "bun",
|
|
@@ -66634,7 +66977,7 @@ var PURE_LIMITS = Object.freeze({
|
|
|
66634
66977
|
maxArtifactsBytes: 0,
|
|
66635
66978
|
maxConcurrency: 1
|
|
66636
66979
|
});
|
|
66637
|
-
var hash2 = (bytes) =>
|
|
66980
|
+
var hash2 = (bytes) => createHash36("sha256").update(bytes).digest("hex");
|
|
66638
66981
|
var object7 = (v2) => {
|
|
66639
66982
|
if (!v2 || typeof v2 !== "object" || Array.isArray(v2))
|
|
66640
66983
|
throw Error("Pure contract requires an object");
|
|
@@ -66863,7 +67206,7 @@ function verifyRuntimeToken(token, key, admission, attempt, now = Date.now()) {
|
|
|
66863
67206
|
const actual = Buffer.from(token);
|
|
66864
67207
|
return actual.length === expected.length && timingSafeEqual2(actual, expected);
|
|
66865
67208
|
}
|
|
66866
|
-
var hashBytes = (bytes) =>
|
|
67209
|
+
var hashBytes = (bytes) => createHash37("sha256").update(bytes).digest("hex");
|
|
66867
67210
|
|
|
66868
67211
|
// src/server/runtime-api.ts
|
|
66869
67212
|
async function createRuntimeService(options) {
|
|
@@ -73239,7 +73582,7 @@ var localRunExecutor = {
|
|
|
73239
73582
|
// src/sdk/storage.ts
|
|
73240
73583
|
var artifactStorageSeam = ArtifactStorage;
|
|
73241
73584
|
// src/sdk/outputs.ts
|
|
73242
|
-
import { createHash as
|
|
73585
|
+
import { createHash as createHash38 } from "crypto";
|
|
73243
73586
|
class DatabaseOnlyObjectStore {
|
|
73244
73587
|
usesS3 = false;
|
|
73245
73588
|
async materialize(run, artifact, body4) {
|
|
@@ -73286,7 +73629,7 @@ function createGovernedArtifactWriter(options) {
|
|
|
73286
73629
|
const stamped = {
|
|
73287
73630
|
...meta,
|
|
73288
73631
|
byteSize: outputBytes,
|
|
73289
|
-
sha256:
|
|
73632
|
+
sha256: createHash38("sha256").update(persistedBytes).digest("hex"),
|
|
73290
73633
|
visibility: options.visibility ?? config.defaultVisibility,
|
|
73291
73634
|
...config.artifactTtlSeconds !== undefined ? { expiresAt: expiresAtFor(createdAt, config.artifactTtlSeconds) } : {}
|
|
73292
73635
|
};
|
|
@@ -76928,14 +77271,14 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
|
|
|
76928
77271
|
const shape = zod.def.shape;
|
|
76929
77272
|
const propValues = {};
|
|
76930
77273
|
for (const key in shape) {
|
|
76931
|
-
const
|
|
76932
|
-
if (
|
|
77274
|
+
const field3 = shape[key]._zod;
|
|
77275
|
+
if (field3.values) {
|
|
76933
77276
|
if (!Object.prototype.hasOwnProperty.call(propValues, key)) {
|
|
76934
77277
|
assignProp(propValues, key, new Set);
|
|
76935
77278
|
}
|
|
76936
|
-
for (const v2 of
|
|
77279
|
+
for (const v2 of field3.values)
|
|
76937
77280
|
propValues[key].add(v2);
|
|
76938
|
-
if (
|
|
77281
|
+
if (field3.optin !== undefined)
|
|
76939
77282
|
propValues[key].add(undefined);
|
|
76940
77283
|
}
|
|
76941
77284
|
}
|
|
@@ -78348,8 +78691,8 @@ function isRecursive(inst, stack) {
|
|
|
78348
78691
|
return true;
|
|
78349
78692
|
stack.add(inst);
|
|
78350
78693
|
let result = false;
|
|
78351
|
-
const check = (
|
|
78352
|
-
if (!result &&
|
|
78694
|
+
const check = (child2) => {
|
|
78695
|
+
if (!result && child2?._zod && isRecursive(child2, stack))
|
|
78353
78696
|
result = true;
|
|
78354
78697
|
};
|
|
78355
78698
|
const def = inst._zod.def;
|
|
@@ -89128,11 +89471,11 @@ var objectProcessor = (schema, ctx, _json, params) => {
|
|
|
89128
89471
|
}
|
|
89129
89472
|
const allKeys = new Set(Object.keys(shape));
|
|
89130
89473
|
const requiredKeys = new Set([...allKeys].filter((key) => {
|
|
89131
|
-
const
|
|
89474
|
+
const field3 = def.shape[key];
|
|
89132
89475
|
if (ctx.io === "input") {
|
|
89133
|
-
return inputOptin(
|
|
89476
|
+
return inputOptin(field3) === undefined;
|
|
89134
89477
|
} else {
|
|
89135
|
-
return
|
|
89478
|
+
return field3._zod.optout === undefined;
|
|
89136
89479
|
}
|
|
89137
89480
|
}));
|
|
89138
89481
|
if (requiredKeys.size > 0) {
|
|
@@ -92053,7 +92396,7 @@ function date4(params) {
|
|
|
92053
92396
|
return _coercedDate(ZodDate2, params);
|
|
92054
92397
|
}
|
|
92055
92398
|
// src/lib/canonical-json.ts
|
|
92056
|
-
import { createHash as
|
|
92399
|
+
import { createHash as createHash39 } from "crypto";
|
|
92057
92400
|
function canonicalJson3(value, maximumBytes = 2 * 1024 * 1024) {
|
|
92058
92401
|
return canonicalJsonAtDepth(value, maximumBytes, 64);
|
|
92059
92402
|
}
|
|
@@ -92097,7 +92440,7 @@ function canonicalJsonAtDepth(value, maximumBytes, maximumDepth) {
|
|
|
92097
92440
|
return visit3(value, 0);
|
|
92098
92441
|
}
|
|
92099
92442
|
function canonicalJsonSha256(value, maximumBytes) {
|
|
92100
|
-
return
|
|
92443
|
+
return createHash39("sha256").update(canonicalJson3(value, maximumBytes)).digest("hex");
|
|
92101
92444
|
}
|
|
92102
92445
|
|
|
92103
92446
|
// src/lib/remote-recurring-contract.ts
|
|
@@ -92877,17 +93220,17 @@ function runQuoteReceipt(value) {
|
|
|
92877
93220
|
return value;
|
|
92878
93221
|
}
|
|
92879
93222
|
function parseRemoteRunQuote(value) {
|
|
92880
|
-
const
|
|
92881
|
-
runQuoteReceipt(
|
|
92882
|
-
const pricing = object9(
|
|
92883
|
-
if (typeof
|
|
93223
|
+
const quote3 = object9(value);
|
|
93224
|
+
runQuoteReceipt(quote3.quoteReceipt);
|
|
93225
|
+
const pricing = object9(quote3.pricing);
|
|
93226
|
+
if (typeof quote3.skill !== "string" || !/^[a-z0-9][a-z0-9-]*$/.test(quote3.skill))
|
|
92884
93227
|
throw new Error("Invalid quoted skill");
|
|
92885
93228
|
const costCents = creditCount(pricing.costCredits ?? pricing.costCents);
|
|
92886
93229
|
if (pricing.costCredits !== undefined && pricing.costCents !== undefined && pricing.costCents !== costCents)
|
|
92887
93230
|
throw new Error("Inconsistent quoted credit count");
|
|
92888
|
-
if (
|
|
93231
|
+
if (quote3.availability && object9(quote3.availability).status !== "available")
|
|
92889
93232
|
throw new Error("This skill is unavailable for remote execution");
|
|
92890
|
-
return { ...
|
|
93233
|
+
return { ...quote3, skill: quote3.skill, pricing: { ...pricing, costCredits: costCents, costCents, formattedCost: `${costCents} credits` } };
|
|
92891
93234
|
}
|
|
92892
93235
|
function parseRemoteCreditPacks(value) {
|
|
92893
93236
|
if (!Array.isArray(value))
|
|
@@ -92962,14 +93305,14 @@ function creditCheckoutFailure(value, status, key) {
|
|
|
92962
93305
|
}
|
|
92963
93306
|
|
|
92964
93307
|
// src/lib/remote-profile.ts
|
|
92965
|
-
function customerNamePatch(input2,
|
|
92966
|
-
if (!isRecord6(input2) || Object.keys(input2).length !== 1 || !Object.hasOwn(input2,
|
|
93308
|
+
function customerNamePatch(input2, field3) {
|
|
93309
|
+
if (!isRecord6(input2) || Object.keys(input2).length !== 1 || !Object.hasOwn(input2, field3))
|
|
92967
93310
|
throw new Error("Provide only the requested name field.");
|
|
92968
|
-
const value = input2[
|
|
93311
|
+
const value = input2[field3];
|
|
92969
93312
|
if (typeof value !== "string" || /[\p{Cc}\p{Cs}\u2028\u2029]/u.test(value) || !value.trim() || [...value.trim()].length > 100) {
|
|
92970
93313
|
throw new Error("Use a name of 1\u2013100 characters without control characters or newlines.");
|
|
92971
93314
|
}
|
|
92972
|
-
return { [
|
|
93315
|
+
return { [field3]: value.trim() };
|
|
92973
93316
|
}
|
|
92974
93317
|
function isRecord6(value) {
|
|
92975
93318
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
@@ -93014,10 +93357,10 @@ async function readQuoteUnavailableCode(response) {
|
|
|
93014
93357
|
let timer;
|
|
93015
93358
|
let deadlineExceeded = false;
|
|
93016
93359
|
const expired = Symbol("quote body deadline");
|
|
93017
|
-
const deadline = new Promise((
|
|
93360
|
+
const deadline = new Promise((resolve25) => {
|
|
93018
93361
|
timer = setTimeout(() => {
|
|
93019
93362
|
deadlineExceeded = true;
|
|
93020
|
-
|
|
93363
|
+
resolve25(expired);
|
|
93021
93364
|
reader.cancel().catch(() => {});
|
|
93022
93365
|
}, 1500);
|
|
93023
93366
|
});
|
|
@@ -93364,18 +93707,18 @@ class RemoteSkillsClient {
|
|
|
93364
93707
|
const maximum = creditCount(approval.maxCredits ?? approval.maxCostCents ?? 0);
|
|
93365
93708
|
if (approval.maxCostCents !== undefined && approval.maxCostCents !== maximum)
|
|
93366
93709
|
throw new Error("Credit approval fields disagree");
|
|
93367
|
-
const
|
|
93368
|
-
if (
|
|
93369
|
-
throw new RemoteCreditApprovalError(
|
|
93710
|
+
const quote3 = approval.quoteReceipt === undefined ? await this.quoteRun(slug2, input2, args, approval.inputFiles?.length ? approval.inputFiles : undefined) : undefined;
|
|
93711
|
+
if (quote3 && quote3.pricing.costCents > maximum)
|
|
93712
|
+
throw new RemoteCreditApprovalError(quote3.pricing.costCents, maximum);
|
|
93370
93713
|
const capabilities = await this.getCapabilities();
|
|
93371
93714
|
if (!capabilities.capabilities.includes("runs.submit") || capabilities.billing?.boundedRunApproval !== true || capabilities.billing.unit !== "credits") {
|
|
93372
93715
|
throw new Error("The configured server does not support bounded credit approval; refusing remote submission");
|
|
93373
93716
|
}
|
|
93374
|
-
return this.submitRun(
|
|
93717
|
+
return this.submitRun(quote3?.skill ?? slug2, input2, args, {
|
|
93375
93718
|
...approval,
|
|
93376
93719
|
maxCredits: maximum,
|
|
93377
93720
|
maxCostCents: maximum,
|
|
93378
|
-
...(
|
|
93721
|
+
...(quote3?.quoteReceipt ?? approval.quoteReceipt) === undefined ? {} : { quoteReceipt: quote3?.quoteReceipt ?? approval.quoteReceipt }
|
|
93379
93722
|
});
|
|
93380
93723
|
}
|
|
93381
93724
|
async getIdentity() {
|
|
@@ -93976,13 +94319,13 @@ class RemoteSkillsClient {
|
|
|
93976
94319
|
return normalizeUpdatedSincePage(await response.json());
|
|
93977
94320
|
}
|
|
93978
94321
|
}
|
|
93979
|
-
function requireOptionalString(record9,
|
|
93980
|
-
if (record9[
|
|
94322
|
+
function requireOptionalString(record9, field3) {
|
|
94323
|
+
if (record9[field3] === undefined)
|
|
93981
94324
|
return;
|
|
93982
|
-
if (typeof record9[
|
|
93983
|
-
throw new Error(`Remote payload did not match the expected contract (${
|
|
94325
|
+
if (typeof record9[field3] !== "string") {
|
|
94326
|
+
throw new Error(`Remote payload did not match the expected contract (${field3} must be a string when present)`);
|
|
93984
94327
|
}
|
|
93985
|
-
return record9[
|
|
94328
|
+
return record9[field3];
|
|
93986
94329
|
}
|
|
93987
94330
|
var INVALID_SKILL_VERSION_RESPONSE = "Remote skill version payload did not match the expected contract.";
|
|
93988
94331
|
function isVersionRecord(value) {
|
|
@@ -94211,7 +94554,7 @@ async function requestInvitationEmail(origin, action, input2) {
|
|
|
94211
94554
|
}
|
|
94212
94555
|
|
|
94213
94556
|
// src/lib/remote-private-publications.ts
|
|
94214
|
-
import { createHash as
|
|
94557
|
+
import { createHash as createHash40 } from "crypto";
|
|
94215
94558
|
var PRIVATE_PUBLICATION_MAX_BYTES = 16 * 1024 * 1024;
|
|
94216
94559
|
var failures2 = {
|
|
94217
94560
|
INVALID_REQUEST: [400, "The publication request is invalid."],
|
|
@@ -94258,7 +94601,7 @@ var hash4 = (v2) => typeof v2 === "string" && /^[a-f0-9]{64}$/.test(v2);
|
|
|
94258
94601
|
var record10 = (v2) => !!v2 && typeof v2 === "object" && !Array.isArray(v2);
|
|
94259
94602
|
var exact = (v2, keys3) => record10(v2) && Object.keys(v2).sort().join(",") === keys3.sort().join(",");
|
|
94260
94603
|
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));
|
|
94261
|
-
var publicationSha256 = (bytes) =>
|
|
94604
|
+
var publicationSha256 = (bytes) => createHash40("sha256").update(bytes).digest("hex");
|
|
94262
94605
|
function checkedPublicationDeclaration(value) {
|
|
94263
94606
|
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)
|
|
94264
94607
|
return bad();
|
|
@@ -94503,12 +94846,12 @@ class RemotePrivatePublicationsClient {
|
|
|
94503
94846
|
previous = view;
|
|
94504
94847
|
if (!["queued", "verifying"].includes(view.state) || Date.now() >= until)
|
|
94505
94848
|
return view;
|
|
94506
|
-
await new Promise((
|
|
94849
|
+
await new Promise((resolve25) => {
|
|
94507
94850
|
const timer = setTimeout(done, Math.min(1000, until - Date.now()));
|
|
94508
94851
|
function done() {
|
|
94509
94852
|
clearTimeout(timer);
|
|
94510
94853
|
options.signal?.removeEventListener("abort", done);
|
|
94511
|
-
|
|
94854
|
+
resolve25();
|
|
94512
94855
|
}
|
|
94513
94856
|
options.signal?.addEventListener("abort", done, { once: true });
|
|
94514
94857
|
});
|
|
@@ -94741,19 +95084,19 @@ class RemoteSkillsAuthClient {
|
|
|
94741
95084
|
}
|
|
94742
95085
|
// src/lib/private-publication-recovery.ts
|
|
94743
95086
|
import { constants as constants16, closeSync as closeSync19, fsyncSync as fsyncSync7, fstatSync as fstatSync19, lstatSync as lstatSync27, mkdirSync as mkdirSync15, openSync as openSync19, readSync as readSync13, realpathSync as realpathSync16, renameSync as renameSync7, unlinkSync as unlinkSync6, writeFileSync as writeFileSync11 } from "fs";
|
|
94744
|
-
import { dirname as
|
|
95087
|
+
import { dirname as dirname29, isAbsolute as isAbsolute25, join as join43, resolve as resolve25 } from "path";
|
|
94745
95088
|
import { randomUUID as randomUUID12 } from "crypto";
|
|
94746
95089
|
var fail2 = () => {
|
|
94747
95090
|
throw new PrivatePublicationError("PUBLICATION_RECOVERY_INVALID", "The recovery directory is invalid or changed. Preserve it and inspect the existing intent; do not start a replacement automatically.");
|
|
94748
95091
|
};
|
|
94749
95092
|
function safeDirectory(directory) {
|
|
94750
|
-
if (!
|
|
95093
|
+
if (!isAbsolute25(directory) || directory !== resolve25(directory) || realpathSync16(directory) !== directory)
|
|
94751
95094
|
return fail2();
|
|
94752
|
-
for (let path2 = directory;; path2 =
|
|
95095
|
+
for (let path2 = directory;; path2 = dirname29(path2)) {
|
|
94753
95096
|
const stat2 = lstatSync27(path2);
|
|
94754
95097
|
if (!stat2.isDirectory() || stat2.isSymbolicLink())
|
|
94755
95098
|
return fail2();
|
|
94756
|
-
if (path2 ===
|
|
95099
|
+
if (path2 === dirname29(path2))
|
|
94757
95100
|
break;
|
|
94758
95101
|
}
|
|
94759
95102
|
const own2 = lstatSync27(directory);
|
|
@@ -94885,11 +95228,11 @@ async function preparePrivatePublication(client2, sourceDirectory, recoveryDirec
|
|
|
94885
95228
|
phase: "prepared",
|
|
94886
95229
|
intent: null
|
|
94887
95230
|
};
|
|
94888
|
-
if (!
|
|
95231
|
+
if (!isAbsolute25(recoveryDirectory) || resolve25(recoveryDirectory) !== recoveryDirectory || realpathSync16(dirname29(recoveryDirectory)) !== dirname29(recoveryDirectory))
|
|
94889
95232
|
return fail2();
|
|
94890
95233
|
mkdirSync15(recoveryDirectory, { mode: 448 });
|
|
94891
95234
|
safeDirectory(recoveryDirectory);
|
|
94892
|
-
const parent = openSync19(
|
|
95235
|
+
const parent = openSync19(dirname29(recoveryDirectory), constants16.O_RDONLY | constants16.O_NOFOLLOW);
|
|
94893
95236
|
try {
|
|
94894
95237
|
fsyncSync7(parent);
|
|
94895
95238
|
} finally {
|