@hasna/skills 0.10.44 → 0.10.46
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 +17 -0
- package/bin/index.js +765 -662
- package/bin/mcp.js +553 -497
- package/bin/migrate.js +1 -1
- package/bin/server.js +1 -1
- package/bin/worker.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +763 -662
- package/dist/lib/agent-discovery.d.ts +1 -1
- package/dist/lib/agent-integration.d.ts +2 -2
- package/dist/lib/agent-sumi.d.ts +3 -0
- package/dist/lib/claude-settings-witness.d.ts +5 -1
- package/dist/lib/sumi-settings-witness.d.ts +14 -0
- package/dist/sdk/index.js +361 -262
- package/package.json +1 -1
package/bin/mcp.js
CHANGED
|
@@ -20019,7 +20019,7 @@ var package_default;
|
|
|
20019
20019
|
var init_package = __esm(() => {
|
|
20020
20020
|
package_default = {
|
|
20021
20021
|
name: "@hasna/skills",
|
|
20022
|
-
version: "0.10.
|
|
20022
|
+
version: "0.10.46",
|
|
20023
20023
|
description: "Skills library for AI coding agents",
|
|
20024
20024
|
type: "module",
|
|
20025
20025
|
bin: {
|
|
@@ -38209,8 +38209,323 @@ var init_agent_adapters = __esm(() => {
|
|
|
38209
38209
|
INTEGRATION_AGENTS = ["claude", "codex", "gemini", "opencode", "cursor", "hermes", "sumi"];
|
|
38210
38210
|
});
|
|
38211
38211
|
|
|
38212
|
+
// src/lib/claude-settings-witness.ts
|
|
38213
|
+
import { createHash as createHash2 } from "crypto";
|
|
38214
|
+
import { closeSync as closeSync5, constants as constants2, fstatSync as fstatSync5, lstatSync as lstatSync5, openSync as openSync5, readSync as readSync2 } from "fs";
|
|
38215
|
+
import { basename as basename3, dirname as dirname4, isAbsolute as isAbsolute3, resolve as resolve2 } from "path";
|
|
38216
|
+
function need(value, reason) {
|
|
38217
|
+
if (!value)
|
|
38218
|
+
throw new Error(`Claude settings witness ${reason}`);
|
|
38219
|
+
}
|
|
38220
|
+
function absolutePath(value) {
|
|
38221
|
+
need(typeof value === "string" && value.length > 0 && value.length <= CLAUDE_SETTINGS_WITNESS_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute3(value) && resolve2(value) === value, "requires a normalized absolute path");
|
|
38222
|
+
}
|
|
38223
|
+
function parents(path) {
|
|
38224
|
+
const result = [];
|
|
38225
|
+
for (let at = dirname4(path);; at = dirname4(at)) {
|
|
38226
|
+
const stat = lstatSync5(at, { bigint: true });
|
|
38227
|
+
need(stat.isDirectory() && !stat.isSymbolicLink(), "path traverses a symlink or non-directory");
|
|
38228
|
+
result.push([at, stat]);
|
|
38229
|
+
if (at === dirname4(at))
|
|
38230
|
+
return result;
|
|
38231
|
+
}
|
|
38232
|
+
}
|
|
38233
|
+
function readNativeSettingsWitnessFile(path, budget, filename = "settings.json") {
|
|
38234
|
+
absolutePath(path);
|
|
38235
|
+
need(basename3(path) === filename, `requires ${filename}`);
|
|
38236
|
+
need(Number.isSafeInteger(budget.remaining) && budget.remaining >= 0, "has an invalid byte budget");
|
|
38237
|
+
const ancestors = parents(path), initial = lstatSync5(path, { bigint: true });
|
|
38238
|
+
need(initial.isFile() && !initial.isSymbolicLink() && initial.size <= BigInt(CLAUDE_SETTINGS_WITNESS_LIMITS.bytes), "is not a bounded regular file");
|
|
38239
|
+
need(initial.size <= BigInt(budget.remaining), "exceeds its aggregate byte limit");
|
|
38240
|
+
const fd = openSync5(path, constants2.O_RDONLY | constants2.O_NOFOLLOW | constants2.O_NONBLOCK);
|
|
38241
|
+
try {
|
|
38242
|
+
const opened = fstatSync5(fd, { bigint: true });
|
|
38243
|
+
need(opened.isFile() && sameFile(initial, opened), "changed during open");
|
|
38244
|
+
const bytes = Buffer.alloc(Number(opened.size) + 1);
|
|
38245
|
+
let length = 0;
|
|
38246
|
+
while (length < bytes.length) {
|
|
38247
|
+
const count = readSync2(fd, bytes, length, bytes.length - length, null);
|
|
38248
|
+
if (!count)
|
|
38249
|
+
break;
|
|
38250
|
+
length += count;
|
|
38251
|
+
}
|
|
38252
|
+
const after = fstatSync5(fd, { bigint: true }), current = lstatSync5(path, { bigint: true });
|
|
38253
|
+
need(current.isFile() && sameFile(opened, after) && sameFile(after, current) && BigInt(length) === opened.size, "changed during read");
|
|
38254
|
+
for (const [ancestor, before] of ancestors) {
|
|
38255
|
+
const now = lstatSync5(ancestor, { bigint: true });
|
|
38256
|
+
need(now.isDirectory() && before.dev === now.dev && before.ino === now.ino && before.mode === now.mode, "parent changed during read");
|
|
38257
|
+
}
|
|
38258
|
+
budget.remaining -= length;
|
|
38259
|
+
try {
|
|
38260
|
+
return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes.subarray(0, length));
|
|
38261
|
+
} catch {
|
|
38262
|
+
throw new Error("Claude settings witness is not strict UTF-8");
|
|
38263
|
+
}
|
|
38264
|
+
} finally {
|
|
38265
|
+
closeSync5(fd);
|
|
38266
|
+
}
|
|
38267
|
+
}
|
|
38268
|
+
function parse6(text) {
|
|
38269
|
+
let at = 0, nodes = 0;
|
|
38270
|
+
const numberPattern = /-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?/y;
|
|
38271
|
+
const space = () => {
|
|
38272
|
+
while (at < text.length && /[\x20\t\r\n]/.test(text[at]))
|
|
38273
|
+
at++;
|
|
38274
|
+
};
|
|
38275
|
+
function string5() {
|
|
38276
|
+
need(text[at] === '"', "contains invalid JSON");
|
|
38277
|
+
const start = at++;
|
|
38278
|
+
while (at < text.length) {
|
|
38279
|
+
const character = text[at++];
|
|
38280
|
+
if (character === '"') {
|
|
38281
|
+
let value2;
|
|
38282
|
+
try {
|
|
38283
|
+
value2 = JSON.parse(text.slice(start, at));
|
|
38284
|
+
} catch {
|
|
38285
|
+
throw new Error("Claude settings witness contains invalid JSON string");
|
|
38286
|
+
}
|
|
38287
|
+
need(value2.length <= CLAUDE_SETTINGS_WITNESS_LIMITS.stringCharacters, "exceeds its string limit");
|
|
38288
|
+
return value2;
|
|
38289
|
+
}
|
|
38290
|
+
if (character === "\\")
|
|
38291
|
+
at++;
|
|
38292
|
+
}
|
|
38293
|
+
throw new Error("Claude settings witness contains an unterminated JSON string");
|
|
38294
|
+
}
|
|
38295
|
+
function value(depth) {
|
|
38296
|
+
need(depth <= CLAUDE_SETTINGS_WITNESS_LIMITS.depth && ++nodes <= CLAUDE_SETTINGS_WITNESS_LIMITS.nodes, "exceeds its nesting or node limit");
|
|
38297
|
+
space();
|
|
38298
|
+
const character = text[at];
|
|
38299
|
+
if (character === '"')
|
|
38300
|
+
return { kind: "string", value: string5() };
|
|
38301
|
+
if (character === "{" || character === "[") {
|
|
38302
|
+
at++;
|
|
38303
|
+
space();
|
|
38304
|
+
const object4 = character === "{", end = object4 ? "}" : "]", entries = [], items = [], keys = new Set;
|
|
38305
|
+
if (text[at] !== end)
|
|
38306
|
+
while (true) {
|
|
38307
|
+
if (object4) {
|
|
38308
|
+
space();
|
|
38309
|
+
const key = string5();
|
|
38310
|
+
need(!keys.has(key), "contains a duplicate JSON key");
|
|
38311
|
+
keys.add(key);
|
|
38312
|
+
space();
|
|
38313
|
+
need(text[at++] === ":", "contains invalid JSON");
|
|
38314
|
+
entries.push([key, value(depth + 1)]);
|
|
38315
|
+
} else
|
|
38316
|
+
items.push(value(depth + 1));
|
|
38317
|
+
space();
|
|
38318
|
+
if (text[at] === end)
|
|
38319
|
+
break;
|
|
38320
|
+
need(text[at++] === ",", "contains invalid JSON");
|
|
38321
|
+
}
|
|
38322
|
+
at++;
|
|
38323
|
+
return object4 ? { kind: "object", entries } : { kind: "array", items };
|
|
38324
|
+
}
|
|
38325
|
+
for (const literal3 of ["true", "false", "null"])
|
|
38326
|
+
if (text.startsWith(literal3, at)) {
|
|
38327
|
+
at += literal3.length;
|
|
38328
|
+
return { kind: "literal", value: literal3 };
|
|
38329
|
+
}
|
|
38330
|
+
numberPattern.lastIndex = at;
|
|
38331
|
+
const number5 = numberPattern.exec(text);
|
|
38332
|
+
need(number5, "contains invalid JSON");
|
|
38333
|
+
at += number5[0].length;
|
|
38334
|
+
return { kind: "number", value: number5[0] };
|
|
38335
|
+
}
|
|
38336
|
+
const root = value(0);
|
|
38337
|
+
space();
|
|
38338
|
+
need(at === text.length && root.kind === "object", "requires a JSON object without trailing content");
|
|
38339
|
+
need(root.entries.length <= CLAUDE_SETTINGS_WITNESS_LIMITS.rows, "exceeds its settings field limit");
|
|
38340
|
+
return root;
|
|
38341
|
+
}
|
|
38342
|
+
function canonical(value) {
|
|
38343
|
+
if (value.kind === "object")
|
|
38344
|
+
return { kind: "object", entries: value.entries.map(([key, child]) => [key, canonical(child)]).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0) };
|
|
38345
|
+
if (value.kind === "array")
|
|
38346
|
+
return { kind: "array", items: value.items.map(canonical) };
|
|
38347
|
+
return value;
|
|
38348
|
+
}
|
|
38349
|
+
function inferencePreference(key, child, version2) {
|
|
38350
|
+
if (key === "skipDangerousModePermissionPrompt") {
|
|
38351
|
+
need(child.kind === "literal" && (child.value === "true" || child.value === "false"), "contains an invalid dialog acknowledgment");
|
|
38352
|
+
return false;
|
|
38353
|
+
}
|
|
38354
|
+
if (key === "effortLevel") {
|
|
38355
|
+
need(child.kind === "string" && PERSISTED_EFFORT_LEVELS.has(child.value), "contains an invalid persisted effort level");
|
|
38356
|
+
return true;
|
|
38357
|
+
}
|
|
38358
|
+
if (key !== "modelSettings")
|
|
38359
|
+
return false;
|
|
38360
|
+
need(child.kind === "object", "requires an object of model preferences");
|
|
38361
|
+
child.entries = child.entries.filter(([model, preferences]) => {
|
|
38362
|
+
if (version2 === 2 && !BUILTIN_MODEL_SELECTIONS.has(model) || preferences.kind !== "object" || preferences.entries.length !== 1 || preferences.entries[0][0] !== "effortLevel")
|
|
38363
|
+
return true;
|
|
38364
|
+
const effort = preferences.entries[0][1];
|
|
38365
|
+
need(effort.kind === "string" && PERSISTED_EFFORT_LEVELS.has(effort.value), "contains an invalid persisted model effort level");
|
|
38366
|
+
return false;
|
|
38367
|
+
});
|
|
38368
|
+
return child.entries.length === 0;
|
|
38369
|
+
}
|
|
38370
|
+
function settingsDigest(text, version2 = 1) {
|
|
38371
|
+
const value = parse6(text);
|
|
38372
|
+
value.entries = value.entries.filter(([key, child]) => {
|
|
38373
|
+
if (version2 !== 1 && inferencePreference(key, child, version2))
|
|
38374
|
+
return false;
|
|
38375
|
+
if (key === "model") {
|
|
38376
|
+
need(child.kind === "string", "contains an invalid model selection");
|
|
38377
|
+
return !BUILTIN_MODEL_SELECTIONS.has(child.value);
|
|
38378
|
+
}
|
|
38379
|
+
if (BOOLEAN_PREFERENCES.has(key)) {
|
|
38380
|
+
need(child.kind === "literal" && (child.value === "true" || child.value === "false"), "contains an invalid display preference");
|
|
38381
|
+
return false;
|
|
38382
|
+
}
|
|
38383
|
+
if (Object.hasOwn(ENUM_PREFERENCES, key)) {
|
|
38384
|
+
need(child.kind === "string" && ENUM_PREFERENCES[key].includes(child.value), "contains an invalid display preference");
|
|
38385
|
+
return false;
|
|
38386
|
+
}
|
|
38387
|
+
return true;
|
|
38388
|
+
});
|
|
38389
|
+
return createHash2("sha256").update(`hasna.skills.claude-settings.v${version2}\x00`).update(JSON.stringify(canonical(value))).digest("hex");
|
|
38390
|
+
}
|
|
38391
|
+
function hashClaudeSettingsReplacement(text, budget) {
|
|
38392
|
+
need(typeof text === "string", "requires settings text");
|
|
38393
|
+
const bytes = Buffer.byteLength(text);
|
|
38394
|
+
need(bytes <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes && Number.isSafeInteger(budget.remaining) && budget.remaining >= bytes, "exceeds its byte limit");
|
|
38395
|
+
budget.remaining -= bytes;
|
|
38396
|
+
return settingsDigest(text);
|
|
38397
|
+
}
|
|
38398
|
+
function captureClaudeSettings(path, budget = { remaining: 256 * 1024 * 1024 }) {
|
|
38399
|
+
return { path, hashMode: "claude-settings-v1", sha256: settingsDigest(readNativeSettingsWitnessFile(path, budget)) };
|
|
38400
|
+
}
|
|
38401
|
+
function captureClaudeSettingsV2(path, budget = { remaining: 256 * 1024 * 1024 }) {
|
|
38402
|
+
return { path, hashMode: "claude-settings-v2", sha256: settingsDigest(readNativeSettingsWitnessFile(path, budget), 2) };
|
|
38403
|
+
}
|
|
38404
|
+
function hashClaudeSettingsReplacementV2(text, budget) {
|
|
38405
|
+
need(typeof text === "string", "requires settings text");
|
|
38406
|
+
const bytes = Buffer.byteLength(text);
|
|
38407
|
+
need(bytes <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes && Number.isSafeInteger(budget.remaining) && budget.remaining >= bytes, "exceeds its byte limit");
|
|
38408
|
+
budget.remaining -= bytes;
|
|
38409
|
+
return settingsDigest(text, 2);
|
|
38410
|
+
}
|
|
38411
|
+
function captureClaudeSettingsV3(path, budget = { remaining: 256 * 1024 * 1024 }) {
|
|
38412
|
+
return { path, hashMode: "claude-settings-v3", sha256: settingsDigest(readNativeSettingsWitnessFile(path, budget), 3) };
|
|
38413
|
+
}
|
|
38414
|
+
function hashClaudeSettingsReplacementV3(text, budget) {
|
|
38415
|
+
need(typeof text === "string", "requires settings text");
|
|
38416
|
+
const bytes = Buffer.byteLength(text);
|
|
38417
|
+
need(bytes <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes && Number.isSafeInteger(budget.remaining) && budget.remaining >= bytes, "exceeds its byte limit");
|
|
38418
|
+
budget.remaining -= bytes;
|
|
38419
|
+
return settingsDigest(text, 3);
|
|
38420
|
+
}
|
|
38421
|
+
function hashNativeJsonControls(text, excludedMetadata) {
|
|
38422
|
+
need(Buffer.byteLength(text) <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes, "exceeds its byte limit");
|
|
38423
|
+
const value = parse6(text);
|
|
38424
|
+
value.entries = value.entries.filter(([key, child]) => {
|
|
38425
|
+
if (key !== excludedMetadata)
|
|
38426
|
+
return true;
|
|
38427
|
+
need(child.kind === "string" && child.value.length <= 128, "has invalid version metadata");
|
|
38428
|
+
return false;
|
|
38429
|
+
});
|
|
38430
|
+
return createHash2("sha256").update("hasna.skills.native-json-controls.v1\x00").update(JSON.stringify(canonical(value))).digest("hex");
|
|
38431
|
+
}
|
|
38432
|
+
function hashSumiNativeJsonControls(text) {
|
|
38433
|
+
need(Buffer.byteLength(text) <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes, "exceeds its byte limit");
|
|
38434
|
+
const value = parse6(text);
|
|
38435
|
+
value.entries = value.entries.filter(([key, child]) => {
|
|
38436
|
+
if (key === "$schema" || key === "username") {
|
|
38437
|
+
need(child.kind === "string", "has invalid Sumi display metadata");
|
|
38438
|
+
return false;
|
|
38439
|
+
}
|
|
38440
|
+
if (key !== "experimental")
|
|
38441
|
+
return true;
|
|
38442
|
+
need(child.kind === "object", "requires Sumi experimental controls to be an object");
|
|
38443
|
+
child.entries = child.entries.filter(([name, option]) => {
|
|
38444
|
+
if (name !== "statusline" && name !== "compact_tools")
|
|
38445
|
+
return true;
|
|
38446
|
+
need(option.kind === "literal" && (option.value === "true" || option.value === "false"), "has invalid Sumi display preference");
|
|
38447
|
+
return false;
|
|
38448
|
+
});
|
|
38449
|
+
return child.entries.length > 0;
|
|
38450
|
+
});
|
|
38451
|
+
return createHash2("sha256").update("hasna.skills.sumi-settings.v1\x00").update(JSON.stringify(value)).digest("hex");
|
|
38452
|
+
}
|
|
38453
|
+
var CLAUDE_SETTINGS_WITNESS_LIMITS, sameFile = (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, BOOLEAN_PREFERENCES, ENUM_PREFERENCES, BUILTIN_MODEL_SELECTIONS, PERSISTED_EFFORT_LEVELS;
|
|
38454
|
+
var init_claude_settings_witness = __esm(() => {
|
|
38455
|
+
CLAUDE_SETTINGS_WITNESS_LIMITS = Object.freeze({ bytes: 1024 * 1024, rows: 1024, depth: 32, nodes: 65536, stringCharacters: 16384, pathCharacters: 4096 });
|
|
38456
|
+
BOOLEAN_PREFERENCES = new Set([
|
|
38457
|
+
"autoScrollEnabled",
|
|
38458
|
+
"axScreenReader",
|
|
38459
|
+
"emojiCompletionEnabled",
|
|
38460
|
+
"prefersReducedMotion",
|
|
38461
|
+
"showTurnDuration",
|
|
38462
|
+
"spinnerTipsEnabled",
|
|
38463
|
+
"syntaxHighlightingDisabled",
|
|
38464
|
+
"terminalProgressBarEnabled",
|
|
38465
|
+
"terminalTitleFromRename",
|
|
38466
|
+
"verbose",
|
|
38467
|
+
"wheelScrollAccelerationEnabled"
|
|
38468
|
+
]);
|
|
38469
|
+
ENUM_PREFERENCES = Object.freeze({
|
|
38470
|
+
editorMode: ["normal", "vim"],
|
|
38471
|
+
tui: ["default", "fullscreen"],
|
|
38472
|
+
viewMode: ["default", "verbose", "focus"]
|
|
38473
|
+
});
|
|
38474
|
+
BUILTIN_MODEL_SELECTIONS = new Set([
|
|
38475
|
+
"default",
|
|
38476
|
+
"best",
|
|
38477
|
+
"fable",
|
|
38478
|
+
"fable[1m]",
|
|
38479
|
+
"sonnet",
|
|
38480
|
+
"sonnet[1m]",
|
|
38481
|
+
"opus",
|
|
38482
|
+
"opus[1m]",
|
|
38483
|
+
"haiku",
|
|
38484
|
+
"opusplan",
|
|
38485
|
+
"claude-fable-5-1",
|
|
38486
|
+
"claude-fable-5",
|
|
38487
|
+
"claude-fable-5[1m]",
|
|
38488
|
+
"claude-opus-5",
|
|
38489
|
+
"claude-sonnet-5",
|
|
38490
|
+
"claude-haiku-4-5-20251001",
|
|
38491
|
+
"claude-opus-4-6",
|
|
38492
|
+
"claude-sonnet-4-5",
|
|
38493
|
+
"claude-sonnet-4-5-20250929",
|
|
38494
|
+
"claude-opus-4-8",
|
|
38495
|
+
"claude-opus-4-8[1m]",
|
|
38496
|
+
"claude-opus-4-7",
|
|
38497
|
+
"claude-sonnet-4-6",
|
|
38498
|
+
"claude-opus-4-5-20251101",
|
|
38499
|
+
"claude-opus-4-5",
|
|
38500
|
+
"claude-haiku-4-5",
|
|
38501
|
+
"claude-fable-5-1[1m]",
|
|
38502
|
+
"claude-opus-5[1m]",
|
|
38503
|
+
"claude-opus-4-7[1m]",
|
|
38504
|
+
"claude-opus-4-6[1m]",
|
|
38505
|
+
"claude-sonnet-4-6[1m]"
|
|
38506
|
+
]);
|
|
38507
|
+
PERSISTED_EFFORT_LEVELS = new Set(["low", "medium", "high", "xhigh"]);
|
|
38508
|
+
});
|
|
38509
|
+
|
|
38510
|
+
// src/lib/sumi-settings-witness.ts
|
|
38511
|
+
function hashSumiSettingsReplacement(text, limits) {
|
|
38512
|
+
const bytes = Buffer.byteLength(text);
|
|
38513
|
+
if (bytes > CLAUDE_SETTINGS_WITNESS_LIMITS.bytes || !Number.isSafeInteger(limits.remaining) || limits.remaining < bytes)
|
|
38514
|
+
throw new Error("Sumi settings witness exceeds its byte limit");
|
|
38515
|
+
limits.remaining -= bytes;
|
|
38516
|
+
return hashSumiNativeJsonControls(text);
|
|
38517
|
+
}
|
|
38518
|
+
function captureSumiSettings(path, limits = budget()) {
|
|
38519
|
+
return { path, hashMode: "sumi-settings-v1", sha256: hashSumiNativeJsonControls(readNativeSettingsWitnessFile(path, limits, "sumi.json")) };
|
|
38520
|
+
}
|
|
38521
|
+
var SUMI_DISCOVERY_PROJECTION_FIELDS, budget = () => ({ remaining: 256 * 1024 * 1024 });
|
|
38522
|
+
var init_sumi_settings_witness = __esm(() => {
|
|
38523
|
+
init_claude_settings_witness();
|
|
38524
|
+
SUMI_DISCOVERY_PROJECTION_FIELDS = ["skills", "plugin", "plugins", "permissions"];
|
|
38525
|
+
});
|
|
38526
|
+
|
|
38212
38527
|
// src/lib/agent-policy-limits.ts
|
|
38213
|
-
import { basename as
|
|
38528
|
+
import { basename as basename4, isAbsolute as isAbsolute4, resolve as resolve3 } from "path";
|
|
38214
38529
|
function object4(value) {
|
|
38215
38530
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
38216
38531
|
}
|
|
@@ -38263,7 +38578,7 @@ function assertAgentPolicyCollections(policy) {
|
|
|
38263
38578
|
text(control.pluginId, 1024);
|
|
38264
38579
|
text(control.namespace, 64);
|
|
38265
38580
|
text(control.pluginParent);
|
|
38266
|
-
requireBound(
|
|
38581
|
+
requireBound(isAbsolute4(control.pluginParent) && resolve3(control.pluginParent) === control.pluginParent && /^[a-f0-9]{64}$/.test(control.manifestSha256));
|
|
38267
38582
|
if (control.remotePluginId !== undefined)
|
|
38268
38583
|
requireBound(typeof control.remotePluginId === "string" && /^[A-Za-z0-9_~-]{1,1024}$/.test(control.remotePluginId));
|
|
38269
38584
|
if (control.skillsOnly !== undefined)
|
|
@@ -38281,7 +38596,7 @@ function assertAgentPolicyCollections(policy) {
|
|
|
38281
38596
|
text(control.pluginId, 1024);
|
|
38282
38597
|
text(control.namespace, 64);
|
|
38283
38598
|
text(control.pluginParent);
|
|
38284
|
-
requireBound(!ids.has(control.pluginId) &&
|
|
38599
|
+
requireBound(!ids.has(control.pluginId) && isAbsolute4(control.pluginParent) && resolve3(control.pluginParent) === control.pluginParent && ["local", "git", "npm"].includes(control.sourceType) && typeof control.sourceSha256 === "string" && /^[a-f0-9]{64}$/.test(control.sourceSha256));
|
|
38285
38600
|
ids.add(control.pluginId);
|
|
38286
38601
|
}
|
|
38287
38602
|
}
|
|
@@ -38306,15 +38621,15 @@ function assertAgentPolicyCollections(policy) {
|
|
|
38306
38621
|
requireBound(object4(value));
|
|
38307
38622
|
text(value.agent, 128);
|
|
38308
38623
|
if (value.codexRetiredMaterializations !== undefined) {
|
|
38309
|
-
const proof = record3(value.codexRetiredMaterializations, 3), roots = array3(proof.roots, AGENT_POLICY_LIMITS.discoveryRoots),
|
|
38310
|
-
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && Object.keys(proof).every((key) => ["roots", "parents", "directories"].includes(key)) && roots.length +
|
|
38624
|
+
const proof = record3(value.codexRetiredMaterializations, 3), roots = array3(proof.roots, AGENT_POLICY_LIMITS.discoveryRoots), parents2 = proof.parents === undefined ? [] : array3(proof.parents, AGENT_POLICY_LIMITS.discoveryRoots);
|
|
38625
|
+
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);
|
|
38311
38626
|
for (const root of roots) {
|
|
38312
38627
|
text(root);
|
|
38313
|
-
requireBound(
|
|
38628
|
+
requireBound(isAbsolute4(root) && resolve3(root) === root);
|
|
38314
38629
|
}
|
|
38315
|
-
for (const parent of
|
|
38630
|
+
for (const parent of parents2) {
|
|
38316
38631
|
text(parent);
|
|
38317
|
-
requireBound(
|
|
38632
|
+
requireBound(isAbsolute4(parent) && resolve3(parent) === parent);
|
|
38318
38633
|
}
|
|
38319
38634
|
for (const directory of array3(proof.directories, AGENT_POLICY_LIMITS.discoveryDirectories)) {
|
|
38320
38635
|
requireBound(object4(directory));
|
|
@@ -38334,7 +38649,7 @@ function assertAgentPolicyCollections(policy) {
|
|
|
38334
38649
|
text(input2.namespace, 64);
|
|
38335
38650
|
text(input2.pluginParent);
|
|
38336
38651
|
text(input2.sourceRoot);
|
|
38337
|
-
requireBound(!ids.has(input2.pluginId) && [input2.pluginParent, input2.sourceRoot].every((path) =>
|
|
38652
|
+
requireBound(!ids.has(input2.pluginId) && [input2.pluginParent, input2.sourceRoot].every((path) => isAbsolute4(path) && resolve3(path) === path) && typeof input2.sourceSha256 === "string" && /^[a-f0-9]{64}$/.test(input2.sourceSha256));
|
|
38338
38653
|
ids.add(input2.pluginId);
|
|
38339
38654
|
}
|
|
38340
38655
|
if (proof.directories !== undefined)
|
|
@@ -38351,13 +38666,15 @@ function assertAgentPolicyCollections(policy) {
|
|
|
38351
38666
|
text(source.path);
|
|
38352
38667
|
requireBound(source.sha256 === null || typeof source.sha256 === "string" && /^[a-f0-9]{64}$/.test(source.sha256));
|
|
38353
38668
|
if (source.hashMode !== undefined)
|
|
38354
|
-
requireBound(["bytes", "path-bytes", "claude-plugin-registry", "claude-marketplace-registry", "claude-settings-v1", "claude-settings-v2", "claude-settings-v3", "claude-marketplace-registry-v2", "codex-settings-v1", "codex-settings-v2", "codex-settings-v3", "codex-settings-v4"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
|
|
38669
|
+
requireBound(["bytes", "path-bytes", "claude-plugin-registry", "claude-marketplace-registry", "claude-settings-v1", "claude-settings-v2", "claude-settings-v3", "claude-marketplace-registry-v2", "codex-settings-v1", "codex-settings-v2", "codex-settings-v3", "codex-settings-v4", "sumi-settings-v1"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
|
|
38670
|
+
if (source.hashMode === "sumi-settings-v1")
|
|
38671
|
+
requireBound(agent === "sumi" && value.agent === "sumi" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute4(source.path) && resolve3(source.path) === source.path && basename4(source.path) === "sumi.json");
|
|
38355
38672
|
if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4"))
|
|
38356
|
-
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) &&
|
|
38673
|
+
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute4(source.path) && resolve3(source.path) === source.path && basename4(source.path) === "config.toml");
|
|
38357
38674
|
if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3")
|
|
38358
|
-
requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) &&
|
|
38675
|
+
requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute4(source.path) && resolve3(source.path) === source.path && basename4(source.path) === "settings.json");
|
|
38359
38676
|
if (source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2")
|
|
38360
|
-
requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) &&
|
|
38677
|
+
requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute4(source.path) && resolve3(source.path) === source.path && basename4(source.path) === "known_marketplaces.json");
|
|
38361
38678
|
if (source.hashMode === "claude-plugin-registry") {
|
|
38362
38679
|
requireBound(agent === "claude");
|
|
38363
38680
|
const managed = array3(source.managedPlugins, 64);
|
|
@@ -45285,7 +45602,7 @@ var require_public_api = __commonJS((exports) => {
|
|
|
45285
45602
|
}
|
|
45286
45603
|
return doc2;
|
|
45287
45604
|
}
|
|
45288
|
-
function
|
|
45605
|
+
function parse7(src, reviver, options) {
|
|
45289
45606
|
let _reviver = undefined;
|
|
45290
45607
|
if (typeof reviver === "function") {
|
|
45291
45608
|
_reviver = reviver;
|
|
@@ -45326,7 +45643,7 @@ var require_public_api = __commonJS((exports) => {
|
|
|
45326
45643
|
return value.toString(options);
|
|
45327
45644
|
return new Document.Document(value, _replacer, options).toString(options);
|
|
45328
45645
|
}
|
|
45329
|
-
exports.parse =
|
|
45646
|
+
exports.parse = parse7;
|
|
45330
45647
|
exports.parseAllDocuments = parseAllDocuments;
|
|
45331
45648
|
exports.parseDocument = parseDocument;
|
|
45332
45649
|
exports.stringify = stringify;
|
|
@@ -45382,7 +45699,7 @@ var init_dist = __esm(() => {
|
|
|
45382
45699
|
});
|
|
45383
45700
|
|
|
45384
45701
|
// src/lib/agent-hermes.ts
|
|
45385
|
-
import { dirname as
|
|
45702
|
+
import { dirname as dirname5, isAbsolute as isAbsolute5, join as join10, resolve as resolve4 } from "path";
|
|
45386
45703
|
function object5(value) {
|
|
45387
45704
|
return Boolean(value && typeof value === "object" && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null));
|
|
45388
45705
|
}
|
|
@@ -45416,7 +45733,7 @@ function assertHermesEnvironment(home) {
|
|
|
45416
45733
|
throw new Error(`NATIVE_SKILL_DRIFT: Hermes ${variable} requires a dedicated discovery adapter; unset it before using this adapter`);
|
|
45417
45734
|
}
|
|
45418
45735
|
const selected = process.env.HERMES_HOME?.trim();
|
|
45419
|
-
if (selected && (!
|
|
45736
|
+
if (selected && (!isAbsolute5(selected) || resolve4(selected) !== join10(resolve4(home), ".hermes")))
|
|
45420
45737
|
throw new Error("NATIVE_SKILL_DRIFT: custom Hermes homes/profiles require their own reviewed bridge");
|
|
45421
45738
|
if (process.env.HERMES_ENABLE_PROJECT_PLUGINS?.trim() && !["0", "false", "no", "off"].includes(process.env.HERMES_ENABLE_PROJECT_PLUGINS.trim().toLowerCase()))
|
|
45422
45739
|
throw new Error("NATIVE_SKILL_DRIFT: Hermes project plugins require a dedicated discovery review");
|
|
@@ -45426,189 +45743,189 @@ var init_agent_hermes = __esm(() => {
|
|
|
45426
45743
|
});
|
|
45427
45744
|
|
|
45428
45745
|
// src/lib/agent-discovery-directories.ts
|
|
45429
|
-
import { createHash as
|
|
45430
|
-
import { lstatSync as
|
|
45431
|
-
import { dirname as
|
|
45432
|
-
function
|
|
45746
|
+
import { createHash as createHash3 } from "crypto";
|
|
45747
|
+
import { lstatSync as lstatSync6, opendirSync } from "fs";
|
|
45748
|
+
import { dirname as dirname6, isAbsolute as isAbsolute6, join as join11, resolve as resolve5 } from "path";
|
|
45749
|
+
function need2(value, message) {
|
|
45433
45750
|
if (!value)
|
|
45434
45751
|
throw new Error(message);
|
|
45435
45752
|
}
|
|
45436
45753
|
function safe(path) {
|
|
45437
|
-
|
|
45438
|
-
for (let cursor = path;; cursor =
|
|
45439
|
-
|
|
45440
|
-
if (
|
|
45754
|
+
need2(typeof path === "string" && path.length <= AGENT_POLICY_LIMITS.pathCharacters && isAbsolute6(path) && resolve5(path) === path && !path.includes("\x00"), "Expected a canonical absolute discovery directory path");
|
|
45755
|
+
for (let cursor = path;; cursor = dirname6(cursor)) {
|
|
45756
|
+
need2(!lstatSync6(cursor, { throwIfNoEntry: false })?.isSymbolicLink(), "Refusing symlink native discovery directory");
|
|
45757
|
+
if (dirname6(cursor) === cursor)
|
|
45441
45758
|
break;
|
|
45442
45759
|
}
|
|
45443
45760
|
}
|
|
45444
45761
|
function same(before, after) {
|
|
45445
45762
|
return Boolean(after && after.isDirectory() && before.dev === after.dev && before.ino === after.ino && before.mtimeMs === after.mtimeMs && before.ctimeMs === after.ctimeMs);
|
|
45446
45763
|
}
|
|
45447
|
-
function capture(path,
|
|
45764
|
+
function capture(path, budget2, excludedRoots, omittedRoots = [], rows) {
|
|
45448
45765
|
safe(path);
|
|
45449
45766
|
if (omittedRoots.some((root2) => path === root2 || path.startsWith(root2 + "/")))
|
|
45450
45767
|
return { path, sha256: null };
|
|
45451
|
-
const root =
|
|
45768
|
+
const root = lstatSync6(path, { throwIfNoEntry: false });
|
|
45452
45769
|
if (!root)
|
|
45453
45770
|
return { path, sha256: null };
|
|
45454
|
-
|
|
45455
|
-
const hash2 =
|
|
45771
|
+
need2(root.isDirectory(), "Unsupported native discovery directory input");
|
|
45772
|
+
const hash2 = createHash3("sha256");
|
|
45456
45773
|
function walk(current, relative3, before, depth) {
|
|
45457
|
-
|
|
45774
|
+
need2(depth <= 64, "Native discovery directory depth limit exceeded");
|
|
45458
45775
|
const names = [], directory = opendirSync(current);
|
|
45459
45776
|
try {
|
|
45460
45777
|
for (let entry = directory.readSync();entry; entry = directory.readSync()) {
|
|
45461
|
-
|
|
45778
|
+
need2(++budget2.entries <= AGENT_POLICY_LIMITS.discoveryDirectoryEntries, "Native discovery directory entry limit exceeded");
|
|
45462
45779
|
names.push(entry.name);
|
|
45463
45780
|
}
|
|
45464
45781
|
} finally {
|
|
45465
45782
|
directory.closeSync();
|
|
45466
45783
|
}
|
|
45467
|
-
|
|
45784
|
+
need2(new Set(names).size === names.length, "Ambiguous native discovery directory names");
|
|
45468
45785
|
for (const name of names.sort()) {
|
|
45469
45786
|
const child = join11(current, name), childRelative = relative3 ? `${relative3}/${name}` : name;
|
|
45470
45787
|
if (omittedRoots.includes(child))
|
|
45471
45788
|
continue;
|
|
45472
|
-
|
|
45473
|
-
const stat =
|
|
45474
|
-
|
|
45789
|
+
need2(child.length <= AGENT_POLICY_LIMITS.pathCharacters, "Native discovery directory path limit exceeded");
|
|
45790
|
+
const stat = lstatSync6(child);
|
|
45791
|
+
need2(stat.isFile() || stat.isDirectory(), "Refusing symlink or special native discovery directory member");
|
|
45475
45792
|
const row = JSON.stringify([childRelative, stat.isDirectory() ? "directory" : "file"]) + `
|
|
45476
45793
|
`;
|
|
45477
|
-
|
|
45478
|
-
|
|
45794
|
+
budget2.bytes += Buffer.byteLength(row);
|
|
45795
|
+
need2(budget2.bytes <= AGENT_POLICY_LIMITS.discoveryDirectoryBytes, "Native discovery directory metadata limit exceeded");
|
|
45479
45796
|
hash2.update(row);
|
|
45480
45797
|
rows?.push(row);
|
|
45481
45798
|
if (stat.isDirectory() && !excludedRoots.includes(child))
|
|
45482
45799
|
walk(child, childRelative, stat, depth + 1);
|
|
45483
45800
|
}
|
|
45484
|
-
|
|
45801
|
+
need2(same(before, lstatSync6(current, { throwIfNoEntry: false })), "Native discovery directory changed while reading");
|
|
45485
45802
|
}
|
|
45486
45803
|
walk(path, "", root, 0);
|
|
45487
45804
|
safe(path);
|
|
45488
45805
|
return { path, sha256: hash2.digest("hex") };
|
|
45489
45806
|
}
|
|
45490
45807
|
function captureDiscoveryDirectoryProjection(paths, omittedRoots) {
|
|
45491
|
-
|
|
45492
|
-
|
|
45808
|
+
need2(Array.isArray(paths) && paths.length <= AGENT_POLICY_LIMITS.discoveryDirectories && new Set(paths).size === paths.length, "Invalid projected discovery directory collection");
|
|
45809
|
+
need2(omittedRoots.length <= AGENT_POLICY_LIMITS.discoveryRoots && new Set(omittedRoots).size === omittedRoots.length, "Invalid inactive discovery roots");
|
|
45493
45810
|
for (const root of omittedRoots)
|
|
45494
45811
|
safe(root);
|
|
45495
|
-
const
|
|
45812
|
+
const budget2 = { entries: 0, bytes: 0 };
|
|
45496
45813
|
return paths.map((path) => {
|
|
45497
45814
|
const entries = [];
|
|
45498
|
-
return { ...capture(path,
|
|
45815
|
+
return { ...capture(path, budget2, [], omittedRoots, entries), entries };
|
|
45499
45816
|
});
|
|
45500
45817
|
}
|
|
45501
45818
|
function verifyDiscoveryDirectoryProjection(directories, omittedRoots) {
|
|
45502
|
-
|
|
45819
|
+
need2(directories.length <= AGENT_POLICY_LIMITS.discoveryDirectories, "Invalid projected discovery directory collection");
|
|
45503
45820
|
let count = 0, bytes = 0;
|
|
45504
45821
|
const expected = directories.map((directory) => {
|
|
45505
45822
|
safe(directory.path);
|
|
45506
|
-
|
|
45507
|
-
const hash2 =
|
|
45823
|
+
need2(Array.isArray(directory.entries), "Missing reviewed directory membership inventory");
|
|
45824
|
+
const hash2 = createHash3("sha256");
|
|
45508
45825
|
const kept = [];
|
|
45509
45826
|
for (const row of directory.entries) {
|
|
45510
|
-
|
|
45827
|
+
need2(typeof row === "string" && ++count <= AGENT_POLICY_LIMITS.discoveryDirectoryEntries, "Invalid reviewed directory membership rows");
|
|
45511
45828
|
bytes += Buffer.byteLength(row);
|
|
45512
|
-
|
|
45829
|
+
need2(bytes <= AGENT_POLICY_LIMITS.discoveryDirectoryBytes, "Reviewed directory membership byte limit exceeded");
|
|
45513
45830
|
const value = JSON.parse(row);
|
|
45514
|
-
|
|
45831
|
+
need2(Array.isArray(value) && value.length === 2 && typeof value[0] === "string" && value[0] && !isAbsolute6(value[0]) && !value[0].split("/").some((part) => !part || part === "." || part === "..") && ["file", "directory"].includes(value[1]) && row === JSON.stringify(value) + `
|
|
45515
45832
|
`, "Invalid reviewed directory member");
|
|
45516
45833
|
hash2.update(row);
|
|
45517
45834
|
const path = join11(directory.path, value[0]);
|
|
45518
45835
|
if (!omittedRoots.some((root) => path === root || path.startsWith(root + "/")))
|
|
45519
45836
|
kept.push(row);
|
|
45520
45837
|
}
|
|
45521
|
-
|
|
45838
|
+
need2(directory.sha256 === null ? directory.entries.length === 0 : hash2.digest("hex") === directory.sha256, "Reviewed directory inventory does not match its fingerprint");
|
|
45522
45839
|
const absent = omittedRoots.some((root) => directory.path === root || directory.path.startsWith(root + "/"));
|
|
45523
|
-
return { path: directory.path, sha256: absent || directory.sha256 === null ? null :
|
|
45840
|
+
return { path: directory.path, sha256: absent || directory.sha256 === null ? null : createHash3("sha256").update(kept.join("")).digest("hex") };
|
|
45524
45841
|
});
|
|
45525
45842
|
const current = captureDiscoveryDirectoryProjection(directories.map((item) => item.path), omittedRoots);
|
|
45526
|
-
|
|
45843
|
+
need2(current.every((item, index) => item.sha256 === expected[index].sha256), "Native discovery directory membership changed outside retired Codex roots");
|
|
45527
45844
|
}
|
|
45528
45845
|
function captureDiscoveryDirectories(paths, excludedRoots = []) {
|
|
45529
|
-
|
|
45530
|
-
const
|
|
45846
|
+
need2(Array.isArray(paths) && paths.length <= AGENT_POLICY_LIMITS.discoveryDirectories && new Set(paths).size === paths.length, "Invalid native discovery directory collection");
|
|
45847
|
+
const budget2 = { entries: 0, bytes: 0 };
|
|
45531
45848
|
for (const root of excludedRoots)
|
|
45532
45849
|
safe(root);
|
|
45533
|
-
return paths.map((path) => capture(path,
|
|
45850
|
+
return paths.map((path) => capture(path, budget2, excludedRoots));
|
|
45534
45851
|
}
|
|
45535
45852
|
function verifyDiscoveryDirectories(directories, excludedRoots = []) {
|
|
45536
|
-
|
|
45853
|
+
need2(Array.isArray(directories) && directories.length <= AGENT_POLICY_LIMITS.discoveryDirectories, "Invalid native discovery directory collection");
|
|
45537
45854
|
for (const directory of directories)
|
|
45538
|
-
|
|
45855
|
+
need2(directory && typeof directory === "object" && (directory.sha256 === null || typeof directory.sha256 === "string" && /^[a-f0-9]{64}$/.test(directory.sha256)), "Invalid native discovery directory digest");
|
|
45539
45856
|
const current = captureDiscoveryDirectories(directories.map((directory) => directory.path), excludedRoots);
|
|
45540
45857
|
for (let i = 0;i < directories.length; i++)
|
|
45541
|
-
|
|
45858
|
+
need2(current[i].sha256 === directories[i].sha256, `Native discovery directory membership changed; run skills hook install with a fresh discovery review: ${directories[i].path}`);
|
|
45542
45859
|
}
|
|
45543
45860
|
var init_agent_discovery_directories = __esm(() => {
|
|
45544
45861
|
init_agent_policy_limits();
|
|
45545
45862
|
});
|
|
45546
45863
|
|
|
45547
45864
|
// src/lib/agent-discovery-bytes.ts
|
|
45548
|
-
import { createHash as
|
|
45549
|
-
import { closeSync as
|
|
45550
|
-
import { dirname as
|
|
45865
|
+
import { createHash as createHash4 } from "crypto";
|
|
45866
|
+
import { closeSync as closeSync6, constants as constants3, fstatSync as fstatSync6, lstatSync as lstatSync7, openSync as openSync6, readSync as readSync3 } from "fs";
|
|
45867
|
+
import { dirname as dirname7, isAbsolute as isAbsolute7, resolve as resolve6 } from "path";
|
|
45551
45868
|
function discoveryByteBudget() {
|
|
45552
45869
|
return { remaining: AGENT_POLICY_LIMITS.discoveryRawTotalBytes };
|
|
45553
45870
|
}
|
|
45554
45871
|
function safe2(path) {
|
|
45555
|
-
if (typeof path !== "string" || !
|
|
45872
|
+
if (typeof path !== "string" || !isAbsolute7(path) || path !== resolve6(path) || path.length > AGENT_POLICY_LIMITS.pathCharacters || path.includes("\x00"))
|
|
45556
45873
|
throw new Error("Expected a canonical absolute raw discovery path");
|
|
45557
|
-
for (let cursor = path;; cursor =
|
|
45558
|
-
if (
|
|
45874
|
+
for (let cursor = path;; cursor = dirname7(cursor)) {
|
|
45875
|
+
if (lstatSync7(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
|
|
45559
45876
|
throw new Error("Refusing symlink raw discovery input");
|
|
45560
|
-
if (
|
|
45877
|
+
if (dirname7(cursor) === cursor)
|
|
45561
45878
|
break;
|
|
45562
45879
|
}
|
|
45563
45880
|
}
|
|
45564
45881
|
function same2(left, right) {
|
|
45565
45882
|
return left.dev === right.dev && left.ino === right.ino && left.size === right.size && left.mtimeMs === right.mtimeMs && left.ctimeMs === right.ctimeMs;
|
|
45566
45883
|
}
|
|
45567
|
-
function consume(
|
|
45568
|
-
if (bytes >
|
|
45884
|
+
function consume(budget2, bytes) {
|
|
45885
|
+
if (bytes > budget2.remaining)
|
|
45569
45886
|
throw new Error("Raw discovery aggregate byte limit exceeded");
|
|
45570
|
-
|
|
45887
|
+
budget2.remaining -= bytes;
|
|
45571
45888
|
}
|
|
45572
|
-
function hashRawDiscoveryFile(path,
|
|
45889
|
+
function hashRawDiscoveryFile(path, budget2, changes) {
|
|
45573
45890
|
safe2(path);
|
|
45574
45891
|
if (changes?.has(path)) {
|
|
45575
45892
|
const text2 = changes.get(path), bytes = Buffer.byteLength(text2);
|
|
45576
45893
|
if (bytes > AGENT_POLICY_LIMITS.discoveryRawSourceBytes)
|
|
45577
45894
|
throw new Error("Raw discovery file byte limit exceeded");
|
|
45578
|
-
consume(
|
|
45579
|
-
return
|
|
45895
|
+
consume(budget2, bytes);
|
|
45896
|
+
return createHash4("sha256").update(text2).digest("hex");
|
|
45580
45897
|
}
|
|
45581
|
-
const initial =
|
|
45898
|
+
const initial = lstatSync7(path, { throwIfNoEntry: false });
|
|
45582
45899
|
if (!initial)
|
|
45583
45900
|
return null;
|
|
45584
45901
|
if (!initial.isFile() || initial.size > AGENT_POLICY_LIMITS.discoveryRawSourceBytes)
|
|
45585
45902
|
throw new Error("Unsupported or oversized raw discovery input");
|
|
45586
|
-
if (initial.size >
|
|
45903
|
+
if (initial.size > budget2.remaining)
|
|
45587
45904
|
throw new Error("Raw discovery aggregate byte limit exceeded");
|
|
45588
|
-
const fd =
|
|
45905
|
+
const fd = openSync6(path, constants3.O_RDONLY | constants3.O_NOFOLLOW | constants3.O_NONBLOCK);
|
|
45589
45906
|
try {
|
|
45590
|
-
const opened =
|
|
45907
|
+
const opened = fstatSync6(fd);
|
|
45591
45908
|
if (!opened.isFile() || !same2(initial, opened))
|
|
45592
45909
|
throw new Error("Raw discovery input changed during open");
|
|
45593
|
-
const hash2 =
|
|
45910
|
+
const hash2 = createHash4("sha256"), buffer = Buffer.alloc(64 * 1024);
|
|
45594
45911
|
let bytes = 0;
|
|
45595
45912
|
while (true) {
|
|
45596
|
-
const count =
|
|
45913
|
+
const count = readSync3(fd, buffer, 0, Math.min(buffer.length, AGENT_POLICY_LIMITS.discoveryRawSourceBytes - bytes + 1), null);
|
|
45597
45914
|
if (!count)
|
|
45598
45915
|
break;
|
|
45599
45916
|
bytes += count;
|
|
45600
45917
|
if (bytes > AGENT_POLICY_LIMITS.discoveryRawSourceBytes)
|
|
45601
45918
|
throw new Error("Raw discovery file byte limit exceeded");
|
|
45602
|
-
consume(
|
|
45919
|
+
consume(budget2, count);
|
|
45603
45920
|
hash2.update(buffer.subarray(0, count));
|
|
45604
45921
|
}
|
|
45605
|
-
const final =
|
|
45922
|
+
const final = fstatSync6(fd), current = lstatSync7(path, { throwIfNoEntry: false });
|
|
45606
45923
|
safe2(path);
|
|
45607
45924
|
if (!current?.isFile() || !same2(opened, final) || !same2(final, current) || bytes !== final.size)
|
|
45608
45925
|
throw new Error("Raw discovery input changed during read");
|
|
45609
45926
|
return hash2.digest("hex");
|
|
45610
45927
|
} finally {
|
|
45611
|
-
|
|
45928
|
+
closeSync6(fd);
|
|
45612
45929
|
}
|
|
45613
45930
|
}
|
|
45614
45931
|
var init_agent_discovery_bytes = __esm(() => {
|
|
@@ -45616,9 +45933,9 @@ var init_agent_discovery_bytes = __esm(() => {
|
|
|
45616
45933
|
});
|
|
45617
45934
|
|
|
45618
45935
|
// src/lib/agent-discovery-path-bytes.ts
|
|
45619
|
-
import { createHash as
|
|
45620
|
-
import { lstatSync as
|
|
45621
|
-
import { dirname as
|
|
45936
|
+
import { createHash as createHash5 } from "crypto";
|
|
45937
|
+
import { lstatSync as lstatSync8, readlinkSync } from "fs";
|
|
45938
|
+
import { dirname as dirname8, isAbsolute as isAbsolute8, join as join12, parse as parse7, resolve as resolve7, sep as sep3 } from "path";
|
|
45622
45939
|
function identity2(stat, mutable = false) {
|
|
45623
45940
|
return {
|
|
45624
45941
|
dev: String(stat.dev),
|
|
@@ -45629,14 +45946,14 @@ function identity2(stat, mutable = false) {
|
|
|
45629
45946
|
...mutable ? { size: String(stat.size), mtimeNs: String(stat.mtimeNs), ctimeNs: String(stat.ctimeNs) } : {}
|
|
45630
45947
|
};
|
|
45631
45948
|
}
|
|
45632
|
-
function
|
|
45633
|
-
if (typeof path !== "string" || !
|
|
45949
|
+
function canonical2(path) {
|
|
45950
|
+
if (typeof path !== "string" || !isAbsolute8(path) || path !== resolve7(path) || path.length > AGENT_POLICY_LIMITS.pathCharacters || path.includes("\x00") || Buffer.from(path).toString("utf8") !== path)
|
|
45634
45951
|
throw new Error("Expected a canonical absolute discovery path");
|
|
45635
45952
|
}
|
|
45636
45953
|
function trace(path) {
|
|
45637
|
-
|
|
45954
|
+
canonical2(path);
|
|
45638
45955
|
const rows = [], paths = [];
|
|
45639
|
-
let metadataBytes = 0, steps = 0, links = 0, cursor =
|
|
45956
|
+
let metadataBytes = 0, steps = 0, links = 0, cursor = parse7(path).root, pending = path.slice(cursor.length).split(sep3);
|
|
45640
45957
|
function record4(path2, row) {
|
|
45641
45958
|
const value = { path: path2, ...row };
|
|
45642
45959
|
metadataBytes += Buffer.byteLength(JSON.stringify(value));
|
|
@@ -45646,7 +45963,7 @@ function trace(path) {
|
|
|
45646
45963
|
paths.push(path2);
|
|
45647
45964
|
}
|
|
45648
45965
|
function root() {
|
|
45649
|
-
const stat =
|
|
45966
|
+
const stat = lstatSync8(cursor, { bigint: true });
|
|
45650
45967
|
if (!stat.isDirectory())
|
|
45651
45968
|
throw new Error("Unsupported discovery path root");
|
|
45652
45969
|
record4(cursor, { type: "directory", ...identity2(stat) });
|
|
@@ -45659,13 +45976,13 @@ function trace(path) {
|
|
|
45659
45976
|
if (!component || component === ".")
|
|
45660
45977
|
continue;
|
|
45661
45978
|
if (component === "..") {
|
|
45662
|
-
cursor =
|
|
45979
|
+
cursor = dirname8(cursor);
|
|
45663
45980
|
continue;
|
|
45664
45981
|
}
|
|
45665
45982
|
const candidate = join12(cursor, component);
|
|
45666
45983
|
if (candidate.length > AGENT_POLICY_LIMITS.pathCharacters)
|
|
45667
45984
|
throw new Error("Discovery resolved path length limit exceeded");
|
|
45668
|
-
const stat =
|
|
45985
|
+
const stat = lstatSync8(candidate, { bigint: true, throwIfNoEntry: false });
|
|
45669
45986
|
if (!stat) {
|
|
45670
45987
|
record4(candidate, { type: "missing", remaining: pending });
|
|
45671
45988
|
return { rows, paths, file: null, missing: candidate, metadataBytes };
|
|
@@ -45673,17 +45990,17 @@ function trace(path) {
|
|
|
45673
45990
|
if (stat.isSymbolicLink()) {
|
|
45674
45991
|
if (++links > AGENT_POLICY_LIMITS.discoveryPathLinks || stat.size > BigInt(AGENT_POLICY_LIMITS.pathCharacters))
|
|
45675
45992
|
throw new Error("Discovery path link limit exceeded");
|
|
45676
|
-
const rawTarget = readlinkSync(candidate, { encoding: "buffer" }), target = rawTarget.toString("utf8"), after =
|
|
45993
|
+
const rawTarget = readlinkSync(candidate, { encoding: "buffer" }), target = rawTarget.toString("utf8"), after = lstatSync8(candidate, { bigint: true });
|
|
45677
45994
|
if (!rawTarget.equals(Buffer.from(target, "utf8")))
|
|
45678
45995
|
throw new Error("Unsupported non-UTF8 discovery link target");
|
|
45679
45996
|
if (!target || target.includes("\x00") || Buffer.byteLength(target) > AGENT_POLICY_LIMITS.pathCharacters || !after.isSymbolicLink() || JSON.stringify(identity2(stat, true)) !== JSON.stringify(identity2(after, true)))
|
|
45680
45997
|
throw new Error("Discovery link changed during read");
|
|
45681
45998
|
record4(candidate, { type: "link", target, ...identity2(stat, true) });
|
|
45682
|
-
if (
|
|
45683
|
-
cursor =
|
|
45999
|
+
if (isAbsolute8(target)) {
|
|
46000
|
+
cursor = parse7(target).root;
|
|
45684
46001
|
root();
|
|
45685
46002
|
}
|
|
45686
|
-
const remainder =
|
|
46003
|
+
const remainder = isAbsolute8(target) ? target.slice(parse7(target).root.length) : target;
|
|
45687
46004
|
pending = [...remainder.split(sep3), ...pending];
|
|
45688
46005
|
if (pending.length + steps > AGENT_POLICY_LIMITS.discoveryPathSteps)
|
|
45689
46006
|
throw new Error("Discovery path step limit exceeded");
|
|
@@ -45703,7 +46020,7 @@ function trace(path) {
|
|
|
45703
46020
|
}
|
|
45704
46021
|
throw new Error("Unsupported directory discovery path input");
|
|
45705
46022
|
}
|
|
45706
|
-
function hashDiscoveryPathFile(path,
|
|
46023
|
+
function hashDiscoveryPathFile(path, budget2, changes) {
|
|
45707
46024
|
const before = trace(path);
|
|
45708
46025
|
let createsMissingPath = false;
|
|
45709
46026
|
if (before.missing !== null && changes) {
|
|
@@ -45716,17 +46033,17 @@ function hashDiscoveryPathFile(path, budget, changes) {
|
|
|
45716
46033
|
}
|
|
45717
46034
|
if (createsMissingPath || changes?.has(path) || before.paths.some((path2) => changes?.has(path2)))
|
|
45718
46035
|
throw new Error("Discovery path witness intersects a planned write; use bytes mode for owned configuration");
|
|
45719
|
-
const remaining =
|
|
46036
|
+
const remaining = budget2.pathMetadataRemaining ?? AGENT_POLICY_LIMITS.discoveryPathTotalMetadataBytes;
|
|
45720
46037
|
if (before.metadataBytes > remaining)
|
|
45721
46038
|
throw new Error("Discovery path aggregate metadata limit exceeded");
|
|
45722
|
-
|
|
45723
|
-
const content = before.file === null ? null : hashRawDiscoveryFile(before.file,
|
|
46039
|
+
budget2.pathMetadataRemaining = remaining - before.metadataBytes;
|
|
46040
|
+
const content = before.file === null ? null : hashRawDiscoveryFile(before.file, budget2);
|
|
45724
46041
|
if (before.file !== null && content === null)
|
|
45725
46042
|
throw new Error("Discovery path input changed during read");
|
|
45726
46043
|
const after = trace(path);
|
|
45727
46044
|
if (JSON.stringify(before.rows) !== JSON.stringify(after.rows) || before.file !== after.file)
|
|
45728
46045
|
throw new Error("Discovery path input changed during read");
|
|
45729
|
-
return
|
|
46046
|
+
return createHash5("sha256").update(JSON.stringify({ version: 1, path, rows: before.rows, content })).digest("hex");
|
|
45730
46047
|
}
|
|
45731
46048
|
var init_agent_discovery_path_bytes = __esm(() => {
|
|
45732
46049
|
init_agent_policy_limits();
|
|
@@ -45734,7 +46051,7 @@ var init_agent_discovery_path_bytes = __esm(() => {
|
|
|
45734
46051
|
});
|
|
45735
46052
|
|
|
45736
46053
|
// src/lib/skill-bundle.ts
|
|
45737
|
-
import { createHash as
|
|
46054
|
+
import { createHash as createHash6 } from "crypto";
|
|
45738
46055
|
import { readFileSync as readFileSync9, readdirSync as readdirSync4, statSync as statSync6 } from "fs";
|
|
45739
46056
|
import { join as join13, relative as relative3 } from "path";
|
|
45740
46057
|
import { createGunzip } from "zlib";
|
|
@@ -45766,7 +46083,7 @@ function ownBytes(view) {
|
|
|
45766
46083
|
return out;
|
|
45767
46084
|
}
|
|
45768
46085
|
function sha256Hex(bytes) {
|
|
45769
|
-
return
|
|
46086
|
+
return createHash6("sha256").update(bytes).digest("hex");
|
|
45770
46087
|
}
|
|
45771
46088
|
function collectSkillBundleEntries(dir) {
|
|
45772
46089
|
const entries = [];
|
|
@@ -45944,7 +46261,7 @@ async function inspectSkillBundle(bundle, options = {}) {
|
|
|
45944
46261
|
parser2.push(chunk);
|
|
45945
46262
|
bytesSinceYield += chunk.byteLength;
|
|
45946
46263
|
if (bytesSinceYield >= 256 * 1024) {
|
|
45947
|
-
await new Promise((
|
|
46264
|
+
await new Promise((resolve8) => setTimeout(resolve8, 0));
|
|
45948
46265
|
bytesSinceYield = 0;
|
|
45949
46266
|
check2();
|
|
45950
46267
|
}
|
|
@@ -46301,21 +46618,21 @@ var init_profile_limits = __esm(() => {
|
|
|
46301
46618
|
});
|
|
46302
46619
|
|
|
46303
46620
|
// src/lib/selection-cache.ts
|
|
46304
|
-
import { createHash as
|
|
46621
|
+
import { createHash as createHash7, randomUUID } from "crypto";
|
|
46305
46622
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
46306
|
-
import { closeSync as
|
|
46623
|
+
import { closeSync as closeSync7, constants as constants4, fstatSync as fstatSync7, fsyncSync, linkSync, lstatSync as lstatSync9, mkdirSync as mkdirSync3, openSync as openSync7, readFileSync as readFileSync10, readlinkSync as readlinkSync2, readSync as readSync4, renameSync, unlinkSync, writeFileSync as writeFileSync3 } from "fs";
|
|
46307
46624
|
import { hostname as hostname3 } from "os";
|
|
46308
|
-
import { dirname as
|
|
46625
|
+
import { dirname as dirname9, join as join14, parse as parse8, resolve as resolve8 } from "path";
|
|
46309
46626
|
import { isDeepStrictEqual } from "util";
|
|
46310
46627
|
function selectionCacheRoot(options = {}) {
|
|
46311
|
-
return
|
|
46628
|
+
return resolve8(options.cacheDir ?? join14(getDataDirReadOnly(), "selection-cache"));
|
|
46312
46629
|
}
|
|
46313
46630
|
function selectionKey(selection) {
|
|
46314
46631
|
validateSelection(selection);
|
|
46315
46632
|
return hash2([selection.authority, selection.workspaceId, selection.slug, selection.version, selection.bundleDigest]);
|
|
46316
46633
|
}
|
|
46317
46634
|
function hash2(value) {
|
|
46318
|
-
return
|
|
46635
|
+
return createHash7("sha256").update(JSON.stringify(value)).digest("hex");
|
|
46319
46636
|
}
|
|
46320
46637
|
function validateSelection(selection) {
|
|
46321
46638
|
if (!selection || !/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(selection.slug) || !isValidSkillVersion(selection.version) || !/^sha256:[a-f0-9]{64}$/.test(selection.bundleDigest) || typeof selection.workspaceId !== "string" || !selection.workspaceId.trim() || typeof selection.profileRevision !== "string" || !selection.profileRevision.trim()) {
|
|
@@ -46355,14 +46672,14 @@ function selectionBundlePath(selection, options = {}) {
|
|
|
46355
46672
|
return join14(selectionCacheRoot(options), "objects", hash2(selection.authority), hash2(selection.workspaceId), `${selection.bundleDigest.slice(7)}.tar.gz`);
|
|
46356
46673
|
}
|
|
46357
46674
|
function assertRegularPath(path, createParents = false) {
|
|
46358
|
-
const absolute =
|
|
46359
|
-
const root =
|
|
46675
|
+
const absolute = resolve8(path);
|
|
46676
|
+
const root = parse8(absolute).root;
|
|
46360
46677
|
let cursor = root;
|
|
46361
46678
|
const segments = absolute.slice(root.length).split("/");
|
|
46362
46679
|
for (let index = 0;index < segments.length; index++) {
|
|
46363
46680
|
cursor = join14(cursor, segments[index]);
|
|
46364
46681
|
try {
|
|
46365
|
-
const stat =
|
|
46682
|
+
const stat = lstatSync9(cursor);
|
|
46366
46683
|
if (stat.isSymbolicLink() || index < segments.length - 1 && !stat.isDirectory()) {
|
|
46367
46684
|
throw new SkillSelectionError("UNSAFE_CACHE_PATH", "Skills cache paths must not traverse symlinks or non-directories.");
|
|
46368
46685
|
}
|
|
@@ -46378,20 +46695,20 @@ function readRegularFile(path, limit) {
|
|
|
46378
46695
|
assertRegularPath(path);
|
|
46379
46696
|
let fd;
|
|
46380
46697
|
try {
|
|
46381
|
-
fd =
|
|
46698
|
+
fd = openSync7(path, constants4.O_RDONLY | constants4.O_NOFOLLOW | constants4.O_NONBLOCK);
|
|
46382
46699
|
} catch (error61) {
|
|
46383
46700
|
if (error61.code === "ENOENT")
|
|
46384
46701
|
return null;
|
|
46385
46702
|
throw error61;
|
|
46386
46703
|
}
|
|
46387
46704
|
try {
|
|
46388
|
-
const stat =
|
|
46705
|
+
const stat = fstatSync7(fd);
|
|
46389
46706
|
if (!stat.isFile() || stat.size > limit)
|
|
46390
46707
|
throw new SkillSelectionError("INVALID_CACHE_FILE", "The Skills cache contains an invalid or oversized file.");
|
|
46391
46708
|
const bytes = Buffer.alloc(stat.size + 1);
|
|
46392
46709
|
let size = 0;
|
|
46393
46710
|
while (size < bytes.length) {
|
|
46394
|
-
const read =
|
|
46711
|
+
const read = readSync4(fd, bytes, size, bytes.length - size, null);
|
|
46395
46712
|
if (!read)
|
|
46396
46713
|
break;
|
|
46397
46714
|
size += read;
|
|
@@ -46400,7 +46717,7 @@ function readRegularFile(path, limit) {
|
|
|
46400
46717
|
throw new SkillSelectionError("INVALID_CACHE_FILE", "The Skills cache file grew during its bounded read.");
|
|
46401
46718
|
return bytes.subarray(0, size);
|
|
46402
46719
|
} finally {
|
|
46403
|
-
|
|
46720
|
+
closeSync7(fd);
|
|
46404
46721
|
}
|
|
46405
46722
|
}
|
|
46406
46723
|
function writeSelectionJson(path, value) {
|
|
@@ -46412,19 +46729,19 @@ function writeSelectionJson(path, value) {
|
|
|
46412
46729
|
}
|
|
46413
46730
|
function atomicWrite(path, bytes, mode, durable = false) {
|
|
46414
46731
|
assertRegularPath(path, true);
|
|
46415
|
-
const temporary = join14(
|
|
46732
|
+
const temporary = join14(dirname9(path), `.selection-${randomUUID()}.tmp`);
|
|
46416
46733
|
try {
|
|
46417
|
-
const fd =
|
|
46734
|
+
const fd = openSync7(temporary, constants4.O_WRONLY | constants4.O_CREAT | constants4.O_EXCL | constants4.O_NOFOLLOW, mode);
|
|
46418
46735
|
try {
|
|
46419
46736
|
writeFileSync3(fd, bytes);
|
|
46420
46737
|
if (durable)
|
|
46421
46738
|
fsyncSync(fd);
|
|
46422
46739
|
} finally {
|
|
46423
|
-
|
|
46740
|
+
closeSync7(fd);
|
|
46424
46741
|
}
|
|
46425
46742
|
renameSync(temporary, path);
|
|
46426
46743
|
if (durable)
|
|
46427
|
-
syncDirectory(
|
|
46744
|
+
syncDirectory(dirname9(path));
|
|
46428
46745
|
} finally {
|
|
46429
46746
|
try {
|
|
46430
46747
|
unlinkSync(temporary);
|
|
@@ -46528,7 +46845,7 @@ function assertFreshCachedProfile(receipt, options = {}) {
|
|
|
46528
46845
|
}
|
|
46529
46846
|
}
|
|
46530
46847
|
function projectSelectionLockPath(projectDir) {
|
|
46531
|
-
return join14(
|
|
46848
|
+
return join14(resolve8(projectDir), ".skills", SELECTION_LOCK_FILE);
|
|
46532
46849
|
}
|
|
46533
46850
|
function readProjectSelection(projectDir) {
|
|
46534
46851
|
const receipt = readSelectionJson(projectSelectionLockPath(projectDir));
|
|
@@ -46636,14 +46953,14 @@ function localLockIdentity() {
|
|
|
46636
46953
|
}
|
|
46637
46954
|
function readSessionLock(sessionId, options) {
|
|
46638
46955
|
const path = `${sessionReceiptPath(sessionId, options)}.write-lock`;
|
|
46639
|
-
const before =
|
|
46956
|
+
const before = lstatSync9(path, { throwIfNoEntry: false });
|
|
46640
46957
|
if (!before)
|
|
46641
46958
|
return null;
|
|
46642
46959
|
if (!before.isFile() || ![1, 2].includes(before.nlink) || (before.mode & 63) !== 0 || process.getuid && before.uid !== process.getuid()) {
|
|
46643
46960
|
throw new SkillSelectionError("SESSION_WRITE_LOCKED", "The session lock is not a private regular file; recovery requires review.");
|
|
46644
46961
|
}
|
|
46645
46962
|
const bytes = readRegularFile(path, SESSION_LOCK_MAX_BYTES);
|
|
46646
|
-
const after =
|
|
46963
|
+
const after = lstatSync9(path, { throwIfNoEntry: false });
|
|
46647
46964
|
if (!bytes || !after?.isFile() || before.dev !== after.dev || before.ino !== after.ino || before.mtimeMs !== after.mtimeMs || before.mode !== after.mode || before.uid !== after.uid || before.gid !== after.gid || before.nlink !== after.nlink) {
|
|
46648
46965
|
throw new SkillSelectionError("SESSION_WRITE_LOCKED", "The session lock changed during inspection; recovery requires review.");
|
|
46649
46966
|
}
|
|
@@ -46660,7 +46977,7 @@ function readSessionLock(sessionId, options) {
|
|
|
46660
46977
|
if (after.nlink === 2) {
|
|
46661
46978
|
stagingPath = `${path}.${marker.operationId}.prepared`;
|
|
46662
46979
|
assertRegularPath(stagingPath);
|
|
46663
|
-
const staged =
|
|
46980
|
+
const staged = lstatSync9(stagingPath, { throwIfNoEntry: false });
|
|
46664
46981
|
if (marker.publication !== "hard-link-v1" || !staged?.isFile() || staged.dev !== after.dev || staged.ino !== after.ino || staged.nlink !== 2 || staged.mode !== after.mode || staged.uid !== after.uid || staged.gid !== after.gid) {
|
|
46665
46982
|
throw new SkillSelectionError("SESSION_WRITE_LOCKED", "The session lock has an unbound publication link; recovery requires review.");
|
|
46666
46983
|
}
|
|
@@ -46671,33 +46988,33 @@ function publishSessionLock(path, marker) {
|
|
|
46671
46988
|
const stagingPath = `${path}.${marker.operationId}.prepared`;
|
|
46672
46989
|
const bytes = Buffer.from(`${JSON.stringify({ ...marker, publication: "hard-link-v1" })}
|
|
46673
46990
|
`);
|
|
46674
|
-
const fd =
|
|
46675
|
-
const stat =
|
|
46991
|
+
const fd = openSync7(stagingPath, constants4.O_WRONLY | constants4.O_CREAT | constants4.O_EXCL | constants4.O_NOFOLLOW, 384);
|
|
46992
|
+
const stat = fstatSync7(fd);
|
|
46676
46993
|
let published = false, handedOff = false;
|
|
46677
46994
|
try {
|
|
46678
46995
|
writeFileSync3(fd, bytes);
|
|
46679
46996
|
fsyncSync(fd);
|
|
46680
46997
|
linkSync(stagingPath, path);
|
|
46681
46998
|
published = true;
|
|
46682
|
-
syncDirectory(
|
|
46683
|
-
const staged =
|
|
46999
|
+
syncDirectory(dirname9(path));
|
|
47000
|
+
const staged = lstatSync9(stagingPath);
|
|
46684
47001
|
if (!staged.isFile() || staged.dev !== stat.dev || staged.ino !== stat.ino) {
|
|
46685
47002
|
throw new SkillSelectionError("SESSION_WRITE_LOCK_CHANGED", "The initialized lock staging inode changed before publication completed.");
|
|
46686
47003
|
}
|
|
46687
47004
|
unlinkSync(stagingPath);
|
|
46688
|
-
syncDirectory(
|
|
47005
|
+
syncDirectory(dirname9(path));
|
|
46689
47006
|
handedOff = true;
|
|
46690
47007
|
return { path, stagingPath, fd, dev: stat.dev, ino: stat.ino };
|
|
46691
47008
|
} finally {
|
|
46692
47009
|
if (!handedOff) {
|
|
46693
47010
|
try {
|
|
46694
47011
|
for (const target of [...published ? [path] : [], stagingPath]) {
|
|
46695
|
-
const current =
|
|
47012
|
+
const current = lstatSync9(target, { throwIfNoEntry: false });
|
|
46696
47013
|
if (current?.isFile() && current.dev === stat.dev && current.ino === stat.ino)
|
|
46697
47014
|
unlinkSync(target);
|
|
46698
47015
|
}
|
|
46699
47016
|
} finally {
|
|
46700
|
-
|
|
47017
|
+
closeSync7(fd);
|
|
46701
47018
|
}
|
|
46702
47019
|
}
|
|
46703
47020
|
}
|
|
@@ -46719,25 +47036,25 @@ function archiveSessionLock(lock, receipt, explicitLocalHost) {
|
|
|
46719
47036
|
const guardPath = `${lock.path}.recovery-guard`;
|
|
46720
47037
|
let guardFd;
|
|
46721
47038
|
try {
|
|
46722
|
-
guardFd =
|
|
47039
|
+
guardFd = openSync7(guardPath, constants4.O_WRONLY | constants4.O_CREAT | constants4.O_EXCL | constants4.O_NOFOLLOW, 384);
|
|
46723
47040
|
} catch (error61) {
|
|
46724
47041
|
if (error61.code === "EEXIST")
|
|
46725
47042
|
return null;
|
|
46726
47043
|
throw error61;
|
|
46727
47044
|
}
|
|
46728
|
-
const guardStat =
|
|
47045
|
+
const guardStat = fstatSync7(guardFd);
|
|
46729
47046
|
try {
|
|
46730
47047
|
writeFileSync3(guardFd, `${JSON.stringify({ schemaVersion: 1, pid: process.pid, operationId: randomUUID() })}
|
|
46731
47048
|
`);
|
|
46732
47049
|
fsyncSync(guardFd);
|
|
46733
|
-
const cacheOptions = { cacheDir:
|
|
47050
|
+
const cacheOptions = { cacheDir: dirname9(dirname9(lock.path)) };
|
|
46734
47051
|
const current = readSessionLock(lock.marker.sessionId, cacheOptions);
|
|
46735
47052
|
if (!current || current.dev !== lock.dev || current.ino !== lock.ino || current.sha256 !== lock.sha256 || current.mtimeMs !== lock.mtimeMs || !writerIsGone(current, explicitLocalHost))
|
|
46736
47053
|
return null;
|
|
46737
47054
|
const currentReceipt = readSkillSessionSnapshotIfExists(lock.marker.sessionId, cacheOptions);
|
|
46738
47055
|
if (currentReceipt?.sha256 !== receipt?.sha256 || currentReceipt?.generation !== receipt?.generation)
|
|
46739
47056
|
return null;
|
|
46740
|
-
const directory = join14(
|
|
47057
|
+
const directory = join14(dirname9(dirname9(lock.path)), "session-lock-recoveries", randomUUID());
|
|
46741
47058
|
const archivePath = join14(directory, "original.write-lock");
|
|
46742
47059
|
const recordPath = join14(directory, "recovery.json");
|
|
46743
47060
|
assertRegularPath(archivePath, true);
|
|
@@ -46754,7 +47071,7 @@ function archiveSessionLock(lock, receipt, explicitLocalHost) {
|
|
|
46754
47071
|
})}
|
|
46755
47072
|
`));
|
|
46756
47073
|
syncDirectory(directory);
|
|
46757
|
-
syncDirectory(
|
|
47074
|
+
syncDirectory(dirname9(directory));
|
|
46758
47075
|
const finalLock = readSessionLock(lock.marker.sessionId, cacheOptions);
|
|
46759
47076
|
if (!finalLock || finalLock.dev !== lock.dev || finalLock.ino !== lock.ino || finalLock.sha256 !== lock.sha256 || readSkillSessionSnapshotIfExists(lock.marker.sessionId, cacheOptions)?.sha256 !== receipt?.sha256)
|
|
46760
47077
|
return null;
|
|
@@ -46769,11 +47086,11 @@ function archiveSessionLock(lock, receipt, explicitLocalHost) {
|
|
|
46769
47086
|
archivedPaths.push(publicationPath);
|
|
46770
47087
|
}
|
|
46771
47088
|
syncDirectory(directory);
|
|
46772
|
-
syncDirectory(
|
|
47089
|
+
syncDirectory(dirname9(lock.path));
|
|
46773
47090
|
for (const path of archivedPaths) {
|
|
46774
|
-
const before =
|
|
47091
|
+
const before = lstatSync9(path, { throwIfNoEntry: false });
|
|
46775
47092
|
const bytes = readRegularFile(path, SESSION_LOCK_MAX_BYTES);
|
|
46776
|
-
const after =
|
|
47093
|
+
const after = lstatSync9(path, { throwIfNoEntry: false });
|
|
46777
47094
|
if (!before?.isFile() || before.dev !== lock.dev || before.ino !== lock.ino || before.nlink !== archivedPaths.length || before.mtimeMs !== lock.mtimeMs || (before.mode & 63) !== 0 || process.getuid && before.uid !== process.getuid() || !bytes || sha256Hex(bytes) !== lock.sha256 || !after?.isFile() || before.dev !== after.dev || before.ino !== after.ino || before.mtimeMs !== after.mtimeMs || before.mode !== after.mode || before.uid !== after.uid || before.gid !== after.gid || before.nlink !== after.nlink) {
|
|
46778
47095
|
throw new Error("Archived lock ownership or bytes changed");
|
|
46779
47096
|
}
|
|
@@ -46785,8 +47102,8 @@ function archiveSessionLock(lock, receipt, explicitLocalHost) {
|
|
|
46785
47102
|
}
|
|
46786
47103
|
return archivePath;
|
|
46787
47104
|
} finally {
|
|
46788
|
-
|
|
46789
|
-
const current =
|
|
47105
|
+
closeSync7(guardFd);
|
|
47106
|
+
const current = lstatSync9(guardPath, { throwIfNoEntry: false });
|
|
46790
47107
|
if (current?.isFile() && current.dev === guardStat.dev && current.ino === guardStat.ino)
|
|
46791
47108
|
unlinkSync(guardPath);
|
|
46792
47109
|
}
|
|
@@ -46798,7 +47115,7 @@ function withSessionWriteLocks(sessionIds, options, action) {
|
|
|
46798
47115
|
const owned = [];
|
|
46799
47116
|
const assertOwned = () => {
|
|
46800
47117
|
for (const lock of owned) {
|
|
46801
|
-
const current =
|
|
47118
|
+
const current = lstatSync9(lock.path, { throwIfNoEntry: false });
|
|
46802
47119
|
if (!current?.isFile() || current.dev !== lock.dev || current.ino !== lock.ino) {
|
|
46803
47120
|
throw new SkillSelectionError("SESSION_WRITE_LOCK_CHANGED", "A session write lock changed during the operation; no replacement is permitted.");
|
|
46804
47121
|
}
|
|
@@ -46842,12 +47159,12 @@ function withSessionWriteLocks(sessionIds, options, action) {
|
|
|
46842
47159
|
for (const lock of owned.reverse()) {
|
|
46843
47160
|
try {
|
|
46844
47161
|
for (const path of [lock.path, lock.stagingPath]) {
|
|
46845
|
-
const current =
|
|
47162
|
+
const current = lstatSync9(path, { throwIfNoEntry: false });
|
|
46846
47163
|
if (current?.isFile() && current.dev === lock.dev && current.ino === lock.ino)
|
|
46847
47164
|
unlinkSync(path);
|
|
46848
47165
|
}
|
|
46849
47166
|
} finally {
|
|
46850
|
-
|
|
47167
|
+
closeSync7(lock.fd);
|
|
46851
47168
|
}
|
|
46852
47169
|
}
|
|
46853
47170
|
}
|
|
@@ -46895,21 +47212,21 @@ function writeSkillSession(receipt, expected, options = {}) {
|
|
|
46895
47212
|
}
|
|
46896
47213
|
function syncDirectory(path) {
|
|
46897
47214
|
assertRegularPath(path);
|
|
46898
|
-
const fd =
|
|
47215
|
+
const fd = openSync7(path, constants4.O_RDONLY | constants4.O_DIRECTORY | constants4.O_NOFOLLOW);
|
|
46899
47216
|
try {
|
|
46900
47217
|
fsyncSync(fd);
|
|
46901
47218
|
} finally {
|
|
46902
|
-
|
|
47219
|
+
closeSync7(fd);
|
|
46903
47220
|
}
|
|
46904
47221
|
}
|
|
46905
47222
|
function archiveBytes(path, bytes) {
|
|
46906
47223
|
assertRegularPath(path, true);
|
|
46907
|
-
const fd =
|
|
47224
|
+
const fd = openSync7(path, constants4.O_WRONLY | constants4.O_CREAT | constants4.O_EXCL | constants4.O_NOFOLLOW, 384);
|
|
46908
47225
|
try {
|
|
46909
47226
|
writeFileSync3(fd, bytes);
|
|
46910
47227
|
fsyncSync(fd);
|
|
46911
47228
|
} finally {
|
|
46912
|
-
|
|
47229
|
+
closeSync7(fd);
|
|
46913
47230
|
}
|
|
46914
47231
|
}
|
|
46915
47232
|
var SkillSelectionError, MAX_CACHED_PROFILE_AGE_MS, SELECTION_LOCK_FILE = "selection.lock.json", SESSION_LOCK_MAX_BYTES = 4096, SESSION_LOCK_MIN_AGE_MS = 30000;
|
|
@@ -46938,7 +47255,7 @@ __export(exports_remote_files, {
|
|
|
46938
47255
|
decodeRemoteFiles: () => decodeRemoteFiles,
|
|
46939
47256
|
MAX_REMOTE_FILE_BYTES: () => MAX_REMOTE_FILE_BYTES
|
|
46940
47257
|
});
|
|
46941
|
-
import { createHash as
|
|
47258
|
+
import { createHash as createHash8 } from "crypto";
|
|
46942
47259
|
function describeRemoteFiles(files) {
|
|
46943
47260
|
if (files.length > 10)
|
|
46944
47261
|
throw new Error("At most 10 input files are supported");
|
|
@@ -46955,7 +47272,7 @@ function describeRemoteFiles(files) {
|
|
|
46955
47272
|
});
|
|
46956
47273
|
}
|
|
46957
47274
|
function sha256(bytes) {
|
|
46958
|
-
return
|
|
47275
|
+
return createHash8("sha256").update(bytes).digest("hex");
|
|
46959
47276
|
}
|
|
46960
47277
|
async function readBoundedResponse(response, maximum) {
|
|
46961
47278
|
if (!Number.isSafeInteger(maximum) || maximum < 0 || maximum > MAX_REMOTE_FILE_BYTES)
|
|
@@ -47210,11 +47527,11 @@ function capturePreparationProcess(child, platform = process.platform, signalGro
|
|
|
47210
47527
|
}
|
|
47211
47528
|
|
|
47212
47529
|
// src/lib/dependency-preparation.ts
|
|
47213
|
-
import { constants as
|
|
47530
|
+
import { constants as constants5, closeSync as closeSync8, fstatSync as fstatSync8, lstatSync as lstatSync10, mkdirSync as mkdirSync4, openSync as openSync8, readFileSync as readFileSync11, readdirSync as readdirSync5, rmdirSync, unlinkSync as unlinkSync2, ftruncateSync, writeSync } from "fs";
|
|
47214
47531
|
import { join as join15 } from "path";
|
|
47215
47532
|
function hasDependencyPreparationMarker(skillPath) {
|
|
47216
47533
|
try {
|
|
47217
|
-
|
|
47534
|
+
lstatSync10(join15(skillPath, DEPENDENCY_PREPARATION_MARKER));
|
|
47218
47535
|
return true;
|
|
47219
47536
|
} catch (error61) {
|
|
47220
47537
|
return error61.code !== "ENOENT";
|
|
@@ -47233,21 +47550,21 @@ function claimPreparation(skillPath) {
|
|
|
47233
47550
|
}
|
|
47234
47551
|
let fd;
|
|
47235
47552
|
try {
|
|
47236
|
-
if (!
|
|
47553
|
+
if (!lstatSync10(marker).isDirectory() || lstatSync10(marker).isSymbolicLink())
|
|
47237
47554
|
return;
|
|
47238
47555
|
if (!created) {
|
|
47239
47556
|
if (readdirSync5(marker).some((name) => name !== "state.json"))
|
|
47240
47557
|
return;
|
|
47241
|
-
if (!
|
|
47558
|
+
if (!lstatSync10(state).isFile() || lstatSync10(state).isSymbolicLink() || lstatSync10(state).size > 1024)
|
|
47242
47559
|
return;
|
|
47243
47560
|
const previous = JSON.parse(readFileSync11(state, "utf8"));
|
|
47244
47561
|
if (previous.version !== 1 || previous.status !== "failed" || Object.keys(previous).length !== 2)
|
|
47245
47562
|
return;
|
|
47246
47563
|
}
|
|
47247
47564
|
mkdirSync4(active, { mode: 448 });
|
|
47248
|
-
fd =
|
|
47249
|
-
if (!
|
|
47250
|
-
|
|
47565
|
+
fd = openSync8(state, constants5.O_RDWR | constants5.O_NOFOLLOW | (created ? constants5.O_CREAT | constants5.O_EXCL : 0), 384);
|
|
47566
|
+
if (!fstatSync8(fd).isFile()) {
|
|
47567
|
+
closeSync8(fd);
|
|
47251
47568
|
return;
|
|
47252
47569
|
}
|
|
47253
47570
|
const descriptor = fd;
|
|
@@ -47259,7 +47576,7 @@ function claimPreparation(skillPath) {
|
|
|
47259
47576
|
record4("pending");
|
|
47260
47577
|
return { abandon() {
|
|
47261
47578
|
try {
|
|
47262
|
-
|
|
47579
|
+
closeSync8(descriptor);
|
|
47263
47580
|
} catch {}
|
|
47264
47581
|
}, finish(success2) {
|
|
47265
47582
|
try {
|
|
@@ -47267,7 +47584,7 @@ function claimPreparation(skillPath) {
|
|
|
47267
47584
|
unlinkSync2(state);
|
|
47268
47585
|
else
|
|
47269
47586
|
record4("failed");
|
|
47270
|
-
|
|
47587
|
+
closeSync8(descriptor);
|
|
47271
47588
|
fd = undefined;
|
|
47272
47589
|
rmdirSync(active);
|
|
47273
47590
|
if (success2)
|
|
@@ -47275,7 +47592,7 @@ function claimPreparation(skillPath) {
|
|
|
47275
47592
|
return true;
|
|
47276
47593
|
} catch {
|
|
47277
47594
|
try {
|
|
47278
|
-
|
|
47595
|
+
closeSync8(descriptor);
|
|
47279
47596
|
} catch {}
|
|
47280
47597
|
return false;
|
|
47281
47598
|
}
|
|
@@ -47283,7 +47600,7 @@ function claimPreparation(skillPath) {
|
|
|
47283
47600
|
} catch {
|
|
47284
47601
|
if (fd !== undefined)
|
|
47285
47602
|
try {
|
|
47286
|
-
|
|
47603
|
+
closeSync8(fd);
|
|
47287
47604
|
} catch {}
|
|
47288
47605
|
return;
|
|
47289
47606
|
}
|
|
@@ -47443,283 +47760,6 @@ function isCodexLocalStdioMcpServer(name, server) {
|
|
|
47443
47760
|
}
|
|
47444
47761
|
}
|
|
47445
47762
|
|
|
47446
|
-
// src/lib/claude-settings-witness.ts
|
|
47447
|
-
import { createHash as createHash8 } from "crypto";
|
|
47448
|
-
import { closeSync as closeSync8, constants as constants5, fstatSync as fstatSync8, lstatSync as lstatSync10, openSync as openSync8, readSync as readSync4 } from "fs";
|
|
47449
|
-
import { basename as basename4, dirname as dirname9, isAbsolute as isAbsolute8, resolve as resolve8 } from "path";
|
|
47450
|
-
function need2(value, reason) {
|
|
47451
|
-
if (!value)
|
|
47452
|
-
throw new Error(`Claude settings witness ${reason}`);
|
|
47453
|
-
}
|
|
47454
|
-
function absolutePath(value) {
|
|
47455
|
-
need2(typeof value === "string" && value.length > 0 && value.length <= CLAUDE_SETTINGS_WITNESS_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute8(value) && resolve8(value) === value, "requires a normalized absolute path");
|
|
47456
|
-
}
|
|
47457
|
-
function parents(path) {
|
|
47458
|
-
const result = [];
|
|
47459
|
-
for (let at = dirname9(path);; at = dirname9(at)) {
|
|
47460
|
-
const stat = lstatSync10(at, { bigint: true });
|
|
47461
|
-
need2(stat.isDirectory() && !stat.isSymbolicLink(), "path traverses a symlink or non-directory");
|
|
47462
|
-
result.push([at, stat]);
|
|
47463
|
-
if (at === dirname9(at))
|
|
47464
|
-
return result;
|
|
47465
|
-
}
|
|
47466
|
-
}
|
|
47467
|
-
function readNativeSettingsWitnessFile(path, budget, filename = "settings.json") {
|
|
47468
|
-
absolutePath(path);
|
|
47469
|
-
need2(basename4(path) === filename, `requires ${filename}`);
|
|
47470
|
-
need2(Number.isSafeInteger(budget.remaining) && budget.remaining >= 0, "has an invalid byte budget");
|
|
47471
|
-
const ancestors = parents(path), initial = lstatSync10(path, { bigint: true });
|
|
47472
|
-
need2(initial.isFile() && !initial.isSymbolicLink() && initial.size <= BigInt(CLAUDE_SETTINGS_WITNESS_LIMITS.bytes), "is not a bounded regular file");
|
|
47473
|
-
need2(initial.size <= BigInt(budget.remaining), "exceeds its aggregate byte limit");
|
|
47474
|
-
const fd = openSync8(path, constants5.O_RDONLY | constants5.O_NOFOLLOW | constants5.O_NONBLOCK);
|
|
47475
|
-
try {
|
|
47476
|
-
const opened = fstatSync8(fd, { bigint: true });
|
|
47477
|
-
need2(opened.isFile() && sameFile(initial, opened), "changed during open");
|
|
47478
|
-
const bytes = Buffer.alloc(Number(opened.size) + 1);
|
|
47479
|
-
let length = 0;
|
|
47480
|
-
while (length < bytes.length) {
|
|
47481
|
-
const count = readSync4(fd, bytes, length, bytes.length - length, null);
|
|
47482
|
-
if (!count)
|
|
47483
|
-
break;
|
|
47484
|
-
length += count;
|
|
47485
|
-
}
|
|
47486
|
-
const after = fstatSync8(fd, { bigint: true }), current = lstatSync10(path, { bigint: true });
|
|
47487
|
-
need2(current.isFile() && sameFile(opened, after) && sameFile(after, current) && BigInt(length) === opened.size, "changed during read");
|
|
47488
|
-
for (const [ancestor, before] of ancestors) {
|
|
47489
|
-
const now = lstatSync10(ancestor, { bigint: true });
|
|
47490
|
-
need2(now.isDirectory() && before.dev === now.dev && before.ino === now.ino && before.mode === now.mode, "parent changed during read");
|
|
47491
|
-
}
|
|
47492
|
-
budget.remaining -= length;
|
|
47493
|
-
try {
|
|
47494
|
-
return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes.subarray(0, length));
|
|
47495
|
-
} catch {
|
|
47496
|
-
throw new Error("Claude settings witness is not strict UTF-8");
|
|
47497
|
-
}
|
|
47498
|
-
} finally {
|
|
47499
|
-
closeSync8(fd);
|
|
47500
|
-
}
|
|
47501
|
-
}
|
|
47502
|
-
function parse8(text2) {
|
|
47503
|
-
let at = 0, nodes = 0;
|
|
47504
|
-
const numberPattern = /-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?/y;
|
|
47505
|
-
const space = () => {
|
|
47506
|
-
while (at < text2.length && /[\x20\t\r\n]/.test(text2[at]))
|
|
47507
|
-
at++;
|
|
47508
|
-
};
|
|
47509
|
-
function string5() {
|
|
47510
|
-
need2(text2[at] === '"', "contains invalid JSON");
|
|
47511
|
-
const start = at++;
|
|
47512
|
-
while (at < text2.length) {
|
|
47513
|
-
const character = text2[at++];
|
|
47514
|
-
if (character === '"') {
|
|
47515
|
-
let value2;
|
|
47516
|
-
try {
|
|
47517
|
-
value2 = JSON.parse(text2.slice(start, at));
|
|
47518
|
-
} catch {
|
|
47519
|
-
throw new Error("Claude settings witness contains invalid JSON string");
|
|
47520
|
-
}
|
|
47521
|
-
need2(value2.length <= CLAUDE_SETTINGS_WITNESS_LIMITS.stringCharacters, "exceeds its string limit");
|
|
47522
|
-
return value2;
|
|
47523
|
-
}
|
|
47524
|
-
if (character === "\\")
|
|
47525
|
-
at++;
|
|
47526
|
-
}
|
|
47527
|
-
throw new Error("Claude settings witness contains an unterminated JSON string");
|
|
47528
|
-
}
|
|
47529
|
-
function value(depth) {
|
|
47530
|
-
need2(depth <= CLAUDE_SETTINGS_WITNESS_LIMITS.depth && ++nodes <= CLAUDE_SETTINGS_WITNESS_LIMITS.nodes, "exceeds its nesting or node limit");
|
|
47531
|
-
space();
|
|
47532
|
-
const character = text2[at];
|
|
47533
|
-
if (character === '"')
|
|
47534
|
-
return { kind: "string", value: string5() };
|
|
47535
|
-
if (character === "{" || character === "[") {
|
|
47536
|
-
at++;
|
|
47537
|
-
space();
|
|
47538
|
-
const object7 = character === "{", end = object7 ? "}" : "]", entries = [], items = [], keys = new Set;
|
|
47539
|
-
if (text2[at] !== end)
|
|
47540
|
-
while (true) {
|
|
47541
|
-
if (object7) {
|
|
47542
|
-
space();
|
|
47543
|
-
const key = string5();
|
|
47544
|
-
need2(!keys.has(key), "contains a duplicate JSON key");
|
|
47545
|
-
keys.add(key);
|
|
47546
|
-
space();
|
|
47547
|
-
need2(text2[at++] === ":", "contains invalid JSON");
|
|
47548
|
-
entries.push([key, value(depth + 1)]);
|
|
47549
|
-
} else
|
|
47550
|
-
items.push(value(depth + 1));
|
|
47551
|
-
space();
|
|
47552
|
-
if (text2[at] === end)
|
|
47553
|
-
break;
|
|
47554
|
-
need2(text2[at++] === ",", "contains invalid JSON");
|
|
47555
|
-
}
|
|
47556
|
-
at++;
|
|
47557
|
-
return object7 ? { kind: "object", entries } : { kind: "array", items };
|
|
47558
|
-
}
|
|
47559
|
-
for (const literal3 of ["true", "false", "null"])
|
|
47560
|
-
if (text2.startsWith(literal3, at)) {
|
|
47561
|
-
at += literal3.length;
|
|
47562
|
-
return { kind: "literal", value: literal3 };
|
|
47563
|
-
}
|
|
47564
|
-
numberPattern.lastIndex = at;
|
|
47565
|
-
const number5 = numberPattern.exec(text2);
|
|
47566
|
-
need2(number5, "contains invalid JSON");
|
|
47567
|
-
at += number5[0].length;
|
|
47568
|
-
return { kind: "number", value: number5[0] };
|
|
47569
|
-
}
|
|
47570
|
-
const root = value(0);
|
|
47571
|
-
space();
|
|
47572
|
-
need2(at === text2.length && root.kind === "object", "requires a JSON object without trailing content");
|
|
47573
|
-
need2(root.entries.length <= CLAUDE_SETTINGS_WITNESS_LIMITS.rows, "exceeds its settings field limit");
|
|
47574
|
-
return root;
|
|
47575
|
-
}
|
|
47576
|
-
function canonical2(value) {
|
|
47577
|
-
if (value.kind === "object")
|
|
47578
|
-
return { kind: "object", entries: value.entries.map(([key, child]) => [key, canonical2(child)]).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0) };
|
|
47579
|
-
if (value.kind === "array")
|
|
47580
|
-
return { kind: "array", items: value.items.map(canonical2) };
|
|
47581
|
-
return value;
|
|
47582
|
-
}
|
|
47583
|
-
function inferencePreference(key, child, version2) {
|
|
47584
|
-
if (key === "skipDangerousModePermissionPrompt") {
|
|
47585
|
-
need2(child.kind === "literal" && (child.value === "true" || child.value === "false"), "contains an invalid dialog acknowledgment");
|
|
47586
|
-
return false;
|
|
47587
|
-
}
|
|
47588
|
-
if (key === "effortLevel") {
|
|
47589
|
-
need2(child.kind === "string" && PERSISTED_EFFORT_LEVELS.has(child.value), "contains an invalid persisted effort level");
|
|
47590
|
-
return true;
|
|
47591
|
-
}
|
|
47592
|
-
if (key !== "modelSettings")
|
|
47593
|
-
return false;
|
|
47594
|
-
need2(child.kind === "object", "requires an object of model preferences");
|
|
47595
|
-
child.entries = child.entries.filter(([model, preferences]) => {
|
|
47596
|
-
if (version2 === 2 && !BUILTIN_MODEL_SELECTIONS.has(model) || preferences.kind !== "object" || preferences.entries.length !== 1 || preferences.entries[0][0] !== "effortLevel")
|
|
47597
|
-
return true;
|
|
47598
|
-
const effort = preferences.entries[0][1];
|
|
47599
|
-
need2(effort.kind === "string" && PERSISTED_EFFORT_LEVELS.has(effort.value), "contains an invalid persisted model effort level");
|
|
47600
|
-
return false;
|
|
47601
|
-
});
|
|
47602
|
-
return child.entries.length === 0;
|
|
47603
|
-
}
|
|
47604
|
-
function settingsDigest(text2, version2 = 1) {
|
|
47605
|
-
const value = parse8(text2);
|
|
47606
|
-
value.entries = value.entries.filter(([key, child]) => {
|
|
47607
|
-
if (version2 !== 1 && inferencePreference(key, child, version2))
|
|
47608
|
-
return false;
|
|
47609
|
-
if (key === "model") {
|
|
47610
|
-
need2(child.kind === "string", "contains an invalid model selection");
|
|
47611
|
-
return !BUILTIN_MODEL_SELECTIONS.has(child.value);
|
|
47612
|
-
}
|
|
47613
|
-
if (BOOLEAN_PREFERENCES.has(key)) {
|
|
47614
|
-
need2(child.kind === "literal" && (child.value === "true" || child.value === "false"), "contains an invalid display preference");
|
|
47615
|
-
return false;
|
|
47616
|
-
}
|
|
47617
|
-
if (Object.hasOwn(ENUM_PREFERENCES, key)) {
|
|
47618
|
-
need2(child.kind === "string" && ENUM_PREFERENCES[key].includes(child.value), "contains an invalid display preference");
|
|
47619
|
-
return false;
|
|
47620
|
-
}
|
|
47621
|
-
return true;
|
|
47622
|
-
});
|
|
47623
|
-
return createHash8("sha256").update(`hasna.skills.claude-settings.v${version2}\x00`).update(JSON.stringify(canonical2(value))).digest("hex");
|
|
47624
|
-
}
|
|
47625
|
-
function hashClaudeSettingsReplacement(text2, budget) {
|
|
47626
|
-
need2(typeof text2 === "string", "requires settings text");
|
|
47627
|
-
const bytes = Buffer.byteLength(text2);
|
|
47628
|
-
need2(bytes <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes && Number.isSafeInteger(budget.remaining) && budget.remaining >= bytes, "exceeds its byte limit");
|
|
47629
|
-
budget.remaining -= bytes;
|
|
47630
|
-
return settingsDigest(text2);
|
|
47631
|
-
}
|
|
47632
|
-
function captureClaudeSettings(path, budget = { remaining: 256 * 1024 * 1024 }) {
|
|
47633
|
-
return { path, hashMode: "claude-settings-v1", sha256: settingsDigest(readNativeSettingsWitnessFile(path, budget)) };
|
|
47634
|
-
}
|
|
47635
|
-
function captureClaudeSettingsV2(path, budget = { remaining: 256 * 1024 * 1024 }) {
|
|
47636
|
-
return { path, hashMode: "claude-settings-v2", sha256: settingsDigest(readNativeSettingsWitnessFile(path, budget), 2) };
|
|
47637
|
-
}
|
|
47638
|
-
function hashClaudeSettingsReplacementV2(text2, budget) {
|
|
47639
|
-
need2(typeof text2 === "string", "requires settings text");
|
|
47640
|
-
const bytes = Buffer.byteLength(text2);
|
|
47641
|
-
need2(bytes <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes && Number.isSafeInteger(budget.remaining) && budget.remaining >= bytes, "exceeds its byte limit");
|
|
47642
|
-
budget.remaining -= bytes;
|
|
47643
|
-
return settingsDigest(text2, 2);
|
|
47644
|
-
}
|
|
47645
|
-
function captureClaudeSettingsV3(path, budget = { remaining: 256 * 1024 * 1024 }) {
|
|
47646
|
-
return { path, hashMode: "claude-settings-v3", sha256: settingsDigest(readNativeSettingsWitnessFile(path, budget), 3) };
|
|
47647
|
-
}
|
|
47648
|
-
function hashClaudeSettingsReplacementV3(text2, budget) {
|
|
47649
|
-
need2(typeof text2 === "string", "requires settings text");
|
|
47650
|
-
const bytes = Buffer.byteLength(text2);
|
|
47651
|
-
need2(bytes <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes && Number.isSafeInteger(budget.remaining) && budget.remaining >= bytes, "exceeds its byte limit");
|
|
47652
|
-
budget.remaining -= bytes;
|
|
47653
|
-
return settingsDigest(text2, 3);
|
|
47654
|
-
}
|
|
47655
|
-
function hashNativeJsonControls(text2, excludedMetadata) {
|
|
47656
|
-
need2(Buffer.byteLength(text2) <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes, "exceeds its byte limit");
|
|
47657
|
-
const value = parse8(text2);
|
|
47658
|
-
value.entries = value.entries.filter(([key, child]) => {
|
|
47659
|
-
if (key !== excludedMetadata)
|
|
47660
|
-
return true;
|
|
47661
|
-
need2(child.kind === "string" && child.value.length <= 128, "has invalid version metadata");
|
|
47662
|
-
return false;
|
|
47663
|
-
});
|
|
47664
|
-
return createHash8("sha256").update("hasna.skills.native-json-controls.v1\x00").update(JSON.stringify(canonical2(value))).digest("hex");
|
|
47665
|
-
}
|
|
47666
|
-
var CLAUDE_SETTINGS_WITNESS_LIMITS, sameFile = (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, BOOLEAN_PREFERENCES, ENUM_PREFERENCES, BUILTIN_MODEL_SELECTIONS, PERSISTED_EFFORT_LEVELS;
|
|
47667
|
-
var init_claude_settings_witness = __esm(() => {
|
|
47668
|
-
CLAUDE_SETTINGS_WITNESS_LIMITS = Object.freeze({ bytes: 1024 * 1024, rows: 1024, depth: 32, nodes: 65536, stringCharacters: 16384, pathCharacters: 4096 });
|
|
47669
|
-
BOOLEAN_PREFERENCES = new Set([
|
|
47670
|
-
"autoScrollEnabled",
|
|
47671
|
-
"axScreenReader",
|
|
47672
|
-
"emojiCompletionEnabled",
|
|
47673
|
-
"prefersReducedMotion",
|
|
47674
|
-
"showTurnDuration",
|
|
47675
|
-
"spinnerTipsEnabled",
|
|
47676
|
-
"syntaxHighlightingDisabled",
|
|
47677
|
-
"terminalProgressBarEnabled",
|
|
47678
|
-
"terminalTitleFromRename",
|
|
47679
|
-
"verbose",
|
|
47680
|
-
"wheelScrollAccelerationEnabled"
|
|
47681
|
-
]);
|
|
47682
|
-
ENUM_PREFERENCES = Object.freeze({
|
|
47683
|
-
editorMode: ["normal", "vim"],
|
|
47684
|
-
tui: ["default", "fullscreen"],
|
|
47685
|
-
viewMode: ["default", "verbose", "focus"]
|
|
47686
|
-
});
|
|
47687
|
-
BUILTIN_MODEL_SELECTIONS = new Set([
|
|
47688
|
-
"default",
|
|
47689
|
-
"best",
|
|
47690
|
-
"fable",
|
|
47691
|
-
"fable[1m]",
|
|
47692
|
-
"sonnet",
|
|
47693
|
-
"sonnet[1m]",
|
|
47694
|
-
"opus",
|
|
47695
|
-
"opus[1m]",
|
|
47696
|
-
"haiku",
|
|
47697
|
-
"opusplan",
|
|
47698
|
-
"claude-fable-5-1",
|
|
47699
|
-
"claude-fable-5",
|
|
47700
|
-
"claude-fable-5[1m]",
|
|
47701
|
-
"claude-opus-5",
|
|
47702
|
-
"claude-sonnet-5",
|
|
47703
|
-
"claude-haiku-4-5-20251001",
|
|
47704
|
-
"claude-opus-4-6",
|
|
47705
|
-
"claude-sonnet-4-5",
|
|
47706
|
-
"claude-sonnet-4-5-20250929",
|
|
47707
|
-
"claude-opus-4-8",
|
|
47708
|
-
"claude-opus-4-8[1m]",
|
|
47709
|
-
"claude-opus-4-7",
|
|
47710
|
-
"claude-sonnet-4-6",
|
|
47711
|
-
"claude-opus-4-5-20251101",
|
|
47712
|
-
"claude-opus-4-5",
|
|
47713
|
-
"claude-haiku-4-5",
|
|
47714
|
-
"claude-fable-5-1[1m]",
|
|
47715
|
-
"claude-opus-5[1m]",
|
|
47716
|
-
"claude-opus-4-7[1m]",
|
|
47717
|
-
"claude-opus-4-6[1m]",
|
|
47718
|
-
"claude-sonnet-4-6[1m]"
|
|
47719
|
-
]);
|
|
47720
|
-
PERSISTED_EFFORT_LEVELS = new Set(["low", "medium", "high", "xhigh"]);
|
|
47721
|
-
});
|
|
47722
|
-
|
|
47723
47763
|
// src/lib/codex-native-compatibility.ts
|
|
47724
47764
|
function supportsCodexNativeCapability(version2, capability) {
|
|
47725
47765
|
return typeof version2 === "string" && Object.hasOwn(MEASURED_CODEX_CAPABILITIES, version2) && MEASURED_CODEX_CAPABILITIES[version2].includes(capability);
|
|
@@ -48060,8 +48100,8 @@ function numericTokens(text2) {
|
|
|
48060
48100
|
}
|
|
48061
48101
|
return result;
|
|
48062
48102
|
}
|
|
48063
|
-
function canonical3(value, depth = 0,
|
|
48064
|
-
need3(depth <= 32 && --
|
|
48103
|
+
function canonical3(value, depth = 0, budget2 = { remaining: 65536 }) {
|
|
48104
|
+
need3(depth <= 32 && --budget2.remaining >= 0);
|
|
48065
48105
|
if (value === null)
|
|
48066
48106
|
return ["null"];
|
|
48067
48107
|
if (typeof value === "string")
|
|
@@ -48077,13 +48117,13 @@ function canonical3(value, depth = 0, budget = { remaining: 65536 }) {
|
|
|
48077
48117
|
return ["date", value.toISOString()];
|
|
48078
48118
|
}
|
|
48079
48119
|
if (Array.isArray(value))
|
|
48080
|
-
return ["array", value.map((child) => canonical3(child, depth + 1,
|
|
48120
|
+
return ["array", value.map((child) => canonical3(child, depth + 1, budget2))];
|
|
48081
48121
|
need3(value && typeof value === "object");
|
|
48082
|
-
return ["object", Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, child]) => [key, canonical3(child, depth + 1,
|
|
48122
|
+
return ["object", Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, child]) => [key, canonical3(child, depth + 1, budget2)])];
|
|
48083
48123
|
}
|
|
48084
|
-
function hashCodexSettingsReplacement(text2,
|
|
48085
|
-
need3(Buffer.byteLength(text2) <= 1024 * 1024 &&
|
|
48086
|
-
|
|
48124
|
+
function hashCodexSettingsReplacement(text2, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
48125
|
+
need3(Buffer.byteLength(text2) <= 1024 * 1024 && budget2.remaining >= Buffer.byteLength(text2));
|
|
48126
|
+
budget2.remaining -= Buffer.byteLength(text2);
|
|
48087
48127
|
let config2;
|
|
48088
48128
|
try {
|
|
48089
48129
|
config2 = Bun.TOML.parse(text2);
|
|
@@ -48102,8 +48142,8 @@ function hashCodexSettingsReplacement(text2, budget = { remaining: 256 * 1024 *
|
|
|
48102
48142
|
}
|
|
48103
48143
|
return sha(`hasna.skills.codex-settings.v1\x00${JSON.stringify([canonical3(config2), numericTokens(text2)])}`);
|
|
48104
48144
|
}
|
|
48105
|
-
function captureCodexSettings(path,
|
|
48106
|
-
const text2 = readNativeSettingsWitnessFile(path,
|
|
48145
|
+
function captureCodexSettings(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
48146
|
+
const text2 = readNativeSettingsWitnessFile(path, budget2, "config.toml");
|
|
48107
48147
|
return { path, hashMode: "codex-settings-v1", sha256: hashCodexSettingsReplacement(text2) };
|
|
48108
48148
|
}
|
|
48109
48149
|
var sha = (text2) => createHash9("sha256").update(text2).digest("hex"), EFFORT, VERBOSITY;
|
|
@@ -48230,8 +48270,8 @@ function numericTokens2(text2) {
|
|
|
48230
48270
|
}
|
|
48231
48271
|
return result.sort();
|
|
48232
48272
|
}
|
|
48233
|
-
function canonical4(value, depth = 0,
|
|
48234
|
-
need4(depth <= 32 && --
|
|
48273
|
+
function canonical4(value, depth = 0, budget2 = { remaining: 65536 }) {
|
|
48274
|
+
need4(depth <= 32 && --budget2.remaining >= 0);
|
|
48235
48275
|
if (value === null)
|
|
48236
48276
|
return ["null"];
|
|
48237
48277
|
if (typeof value === "string")
|
|
@@ -48247,9 +48287,9 @@ function canonical4(value, depth = 0, budget = { remaining: 65536 }) {
|
|
|
48247
48287
|
return ["date", value.toISOString()];
|
|
48248
48288
|
}
|
|
48249
48289
|
if (Array.isArray(value))
|
|
48250
|
-
return ["array", value.map((child) => canonical4(child, depth + 1,
|
|
48290
|
+
return ["array", value.map((child) => canonical4(child, depth + 1, budget2))];
|
|
48251
48291
|
need4(isRecord3(value));
|
|
48252
|
-
return ["object", Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, child]) => [key, canonical4(child, depth + 1,
|
|
48292
|
+
return ["object", Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, child]) => [key, canonical4(child, depth + 1, budget2)])];
|
|
48253
48293
|
}
|
|
48254
48294
|
function normalize2(config2, version2 = 2) {
|
|
48255
48295
|
if (isRecord3(config2.hooks)) {
|
|
@@ -48425,30 +48465,30 @@ function settingsDigest2(text2, version2 = 2) {
|
|
|
48425
48465
|
normalize2(projected.config, version2);
|
|
48426
48466
|
return sha2(`hasna.skills.codex-settings.v${version2}\x00${JSON.stringify([canonical4(projected.config), numericTokens2(projected.numericSource)])}`);
|
|
48427
48467
|
}
|
|
48428
|
-
function hashCodexSettingsReplacementV2(text2,
|
|
48429
|
-
need4(Buffer.byteLength(text2) <= 1024 * 1024 &&
|
|
48430
|
-
|
|
48468
|
+
function hashCodexSettingsReplacementV2(text2, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
48469
|
+
need4(Buffer.byteLength(text2) <= 1024 * 1024 && budget2.remaining >= Buffer.byteLength(text2));
|
|
48470
|
+
budget2.remaining -= Buffer.byteLength(text2);
|
|
48431
48471
|
return settingsDigest2(text2);
|
|
48432
48472
|
}
|
|
48433
|
-
function captureCodexSettingsV2(path,
|
|
48434
|
-
const text2 = readNativeSettingsWitnessFile(path,
|
|
48473
|
+
function captureCodexSettingsV2(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
48474
|
+
const text2 = readNativeSettingsWitnessFile(path, budget2, "config.toml");
|
|
48435
48475
|
return { path, hashMode: "codex-settings-v2", sha256: settingsDigest2(text2) };
|
|
48436
48476
|
}
|
|
48437
|
-
function hashCodexSettingsReplacementV3(text2,
|
|
48438
|
-
need4(Buffer.byteLength(text2) <= 1024 * 1024 &&
|
|
48439
|
-
|
|
48477
|
+
function hashCodexSettingsReplacementV3(text2, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
48478
|
+
need4(Buffer.byteLength(text2) <= 1024 * 1024 && budget2.remaining >= Buffer.byteLength(text2));
|
|
48479
|
+
budget2.remaining -= Buffer.byteLength(text2);
|
|
48440
48480
|
return settingsDigest2(text2, 3);
|
|
48441
48481
|
}
|
|
48442
|
-
function captureCodexSettingsV3(path,
|
|
48443
|
-
return { path, hashMode: "codex-settings-v3", sha256: settingsDigest2(readNativeSettingsWitnessFile(path,
|
|
48482
|
+
function captureCodexSettingsV3(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
48483
|
+
return { path, hashMode: "codex-settings-v3", sha256: settingsDigest2(readNativeSettingsWitnessFile(path, budget2, "config.toml"), 3) };
|
|
48444
48484
|
}
|
|
48445
|
-
function hashCodexSettingsReplacementV4(text2,
|
|
48446
|
-
need4(Buffer.byteLength(text2) <= 1024 * 1024 &&
|
|
48447
|
-
|
|
48485
|
+
function hashCodexSettingsReplacementV4(text2, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
48486
|
+
need4(Buffer.byteLength(text2) <= 1024 * 1024 && budget2.remaining >= Buffer.byteLength(text2));
|
|
48487
|
+
budget2.remaining -= Buffer.byteLength(text2);
|
|
48448
48488
|
return settingsDigest2(text2, 4);
|
|
48449
48489
|
}
|
|
48450
|
-
function captureCodexSettingsV4(path,
|
|
48451
|
-
return { path, hashMode: "codex-settings-v4", sha256: settingsDigest2(readNativeSettingsWitnessFile(path,
|
|
48490
|
+
function captureCodexSettingsV4(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
48491
|
+
return { path, hashMode: "codex-settings-v4", sha256: settingsDigest2(readNativeSettingsWitnessFile(path, budget2, "config.toml"), 4) };
|
|
48452
48492
|
}
|
|
48453
48493
|
var sha2 = (text2) => createHash10("sha256").update(text2).digest("hex"), EFFORT2, VERBOSITY2, MODEL, CODEX_DISCOVERY_PROJECTION_FIELDS, INFERENCE;
|
|
48454
48494
|
var init_codex_settings_witness = __esm(() => {
|
|
@@ -48653,6 +48693,7 @@ var init_codex_hook_trust_files = () => {};
|
|
|
48653
48693
|
|
|
48654
48694
|
// src/lib/agent-integration.ts
|
|
48655
48695
|
var init_agent_integration = __esm(() => {
|
|
48696
|
+
init_sumi_settings_witness();
|
|
48656
48697
|
init_codex_corpus_write();
|
|
48657
48698
|
init_codex_plugin_skill_controls();
|
|
48658
48699
|
init_codex_native_skill_policy();
|
|
@@ -50047,13 +50088,13 @@ function parents2(path) {
|
|
|
50047
50088
|
return result;
|
|
50048
50089
|
}
|
|
50049
50090
|
}
|
|
50050
|
-
function readRegistry2(path,
|
|
50091
|
+
function readRegistry2(path, budget2) {
|
|
50051
50092
|
absolutePath2(path);
|
|
50052
50093
|
need6(basename7(path) === "known_marketplaces.json", "requires known_marketplaces.json");
|
|
50053
|
-
need6(Number.isSafeInteger(
|
|
50094
|
+
need6(Number.isSafeInteger(budget2.remaining) && budget2.remaining >= 0, "has an invalid byte budget");
|
|
50054
50095
|
const ancestors2 = parents2(path), initial = lstatSync17(path, { bigint: true });
|
|
50055
50096
|
need6(initial.isFile() && !initial.isSymbolicLink() && initial.size <= BigInt(CLAUDE_MARKETPLACE_REGISTRY_LIMITS.bytes), "is not a bounded regular file");
|
|
50056
|
-
need6(initial.size <= BigInt(
|
|
50097
|
+
need6(initial.size <= BigInt(budget2.remaining), "exceeds its aggregate byte limit");
|
|
50057
50098
|
const fd = openSync13(path, constants10.O_RDONLY | constants10.O_NOFOLLOW | constants10.O_NONBLOCK);
|
|
50058
50099
|
try {
|
|
50059
50100
|
const opened = fstatSync13(fd, { bigint: true });
|
|
@@ -50072,7 +50113,7 @@ function readRegistry2(path, budget) {
|
|
|
50072
50113
|
const now = lstatSync17(ancestor, { bigint: true });
|
|
50073
50114
|
need6(now.isDirectory() && before.dev === now.dev && before.ino === now.ino && before.mode === now.mode, "parent changed during read");
|
|
50074
50115
|
}
|
|
50075
|
-
|
|
50116
|
+
budget2.remaining -= length;
|
|
50076
50117
|
try {
|
|
50077
50118
|
return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes.subarray(0, length));
|
|
50078
50119
|
} catch {
|
|
@@ -50189,15 +50230,15 @@ function normalizeRow(row, version2 = 1) {
|
|
|
50189
50230
|
need6(Number.isFinite(millis) && new Date(millis).toISOString() === updated, "contains an invalid recognized update timestamp");
|
|
50190
50231
|
row.entries = row.entries.map(([key, value]) => [key, key === "lastUpdated" ? { kind: "validated-update-time" } : value]);
|
|
50191
50232
|
}
|
|
50192
|
-
function captureClaudeMarketplaceRegistry(path,
|
|
50193
|
-
const value = parse10(readRegistry2(path,
|
|
50233
|
+
function captureClaudeMarketplaceRegistry(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
50234
|
+
const value = parse10(readRegistry2(path, budget2));
|
|
50194
50235
|
for (const [, row] of value.entries)
|
|
50195
50236
|
normalizeRow(row);
|
|
50196
50237
|
const sha2562 = createHash14("sha256").update("hasna.skills.claude-marketplace-registry.v1\x00").update(JSON.stringify(value)).digest("hex");
|
|
50197
50238
|
return { path, hashMode: "claude-marketplace-registry", sha256: sha2562 };
|
|
50198
50239
|
}
|
|
50199
|
-
function captureClaudeMarketplaceRegistryV2(path,
|
|
50200
|
-
const value = parse10(readRegistry2(path,
|
|
50240
|
+
function captureClaudeMarketplaceRegistryV2(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
50241
|
+
const value = parse10(readRegistry2(path, budget2));
|
|
50201
50242
|
for (const [, row] of value.entries)
|
|
50202
50243
|
normalizeRow(row, 2);
|
|
50203
50244
|
const sha2562 = createHash14("sha256").update("hasna.skills.claude-marketplace-registry.v2\x00").update(JSON.stringify(value)).digest("hex");
|
|
@@ -50289,33 +50330,45 @@ function projectNativeDiscoveryFields(text2, format, fields2, path) {
|
|
|
50289
50330
|
throw new Error("Expected native discovery configuration object");
|
|
50290
50331
|
return digest(JSON.stringify(Object.fromEntries(fields2.map((field2) => [field2, object7[field2] ?? null]))));
|
|
50291
50332
|
}
|
|
50292
|
-
function
|
|
50333
|
+
function isSupersededSettingsProjection(agent, configPath, source) {
|
|
50334
|
+
if (agent === "sumi")
|
|
50335
|
+
return source.path === configPath && source.format === "json" && isDeepStrictEqual4(source.fields, [...SUMI_DISCOVERY_PROJECTION_FIELDS]);
|
|
50293
50336
|
return agent === "codex" && source.path === configPath && source.format === "toml" && isDeepStrictEqual4(source.fields, [...CODEX_DISCOVERY_PROJECTION_FIELDS]);
|
|
50294
50337
|
}
|
|
50295
|
-
function
|
|
50296
|
-
|
|
50338
|
+
function supersedesSettingsProjection(agent, sources, configPath) {
|
|
50339
|
+
if (agent === "sumi")
|
|
50340
|
+
return sources.some((source) => source.path === configPath && source.hashMode === "sumi-settings-v1");
|
|
50341
|
+
return agent === "codex" && sources.some((source) => source.path === configPath && (source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")));
|
|
50297
50342
|
}
|
|
50298
|
-
function projected(source, changes,
|
|
50343
|
+
function projected(source, changes, budget2 = discoveryByteBudget()) {
|
|
50344
|
+
if (source.hashMode === "sumi-settings-v1") {
|
|
50345
|
+
if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
|
|
50346
|
+
throw new Error("Sumi settings witnesses require exact typed metadata");
|
|
50347
|
+
const current = captureSumiSettings(source.path, budget2).sha256;
|
|
50348
|
+
if (current !== source.sha256)
|
|
50349
|
+
throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
|
|
50350
|
+
return changes?.has(source.path) ? hashSumiSettingsReplacement(changes.get(source.path), budget2) : current;
|
|
50351
|
+
}
|
|
50299
50352
|
if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")) {
|
|
50300
50353
|
if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
|
|
50301
50354
|
throw new Error("Codex settings witnesses require exact typed metadata");
|
|
50302
|
-
const current = (source.hashMode === "codex-settings-v4" ? captureCodexSettingsV4 : source.hashMode === "codex-settings-v3" ? captureCodexSettingsV3 : source.hashMode === "codex-settings-v2" ? captureCodexSettingsV2 : captureCodexSettings)(source.path,
|
|
50355
|
+
const current = (source.hashMode === "codex-settings-v4" ? captureCodexSettingsV4 : source.hashMode === "codex-settings-v3" ? captureCodexSettingsV3 : source.hashMode === "codex-settings-v2" ? captureCodexSettingsV2 : captureCodexSettings)(source.path, budget2).sha256;
|
|
50303
50356
|
if (current !== source.sha256)
|
|
50304
50357
|
throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
|
|
50305
|
-
return changes?.has(source.path) ? (source.hashMode === "codex-settings-v4" ? hashCodexSettingsReplacementV4 : source.hashMode === "codex-settings-v3" ? hashCodexSettingsReplacementV3 : source.hashMode === "codex-settings-v2" ? hashCodexSettingsReplacementV2 : hashCodexSettingsReplacement)(changes.get(source.path),
|
|
50358
|
+
return changes?.has(source.path) ? (source.hashMode === "codex-settings-v4" ? hashCodexSettingsReplacementV4 : source.hashMode === "codex-settings-v3" ? hashCodexSettingsReplacementV3 : source.hashMode === "codex-settings-v2" ? hashCodexSettingsReplacementV2 : hashCodexSettingsReplacement)(changes.get(source.path), budget2) : current;
|
|
50306
50359
|
}
|
|
50307
50360
|
if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") {
|
|
50308
50361
|
if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
|
|
50309
50362
|
throw new Error("Claude settings witnesses require exact typed metadata");
|
|
50310
|
-
const current = (source.hashMode === "claude-settings-v3" ? captureClaudeSettingsV3 : source.hashMode === "claude-settings-v2" ? captureClaudeSettingsV2 : captureClaudeSettings)(source.path,
|
|
50363
|
+
const current = (source.hashMode === "claude-settings-v3" ? captureClaudeSettingsV3 : source.hashMode === "claude-settings-v2" ? captureClaudeSettingsV2 : captureClaudeSettings)(source.path, budget2).sha256;
|
|
50311
50364
|
if (current !== source.sha256)
|
|
50312
50365
|
throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
|
|
50313
|
-
return changes?.has(source.path) ? (source.hashMode === "claude-settings-v3" ? hashClaudeSettingsReplacementV3 : source.hashMode === "claude-settings-v2" ? hashClaudeSettingsReplacementV2 : hashClaudeSettingsReplacement)(changes.get(source.path),
|
|
50366
|
+
return changes?.has(source.path) ? (source.hashMode === "claude-settings-v3" ? hashClaudeSettingsReplacementV3 : source.hashMode === "claude-settings-v2" ? hashClaudeSettingsReplacementV2 : hashClaudeSettingsReplacement)(changes.get(source.path), budget2) : current;
|
|
50314
50367
|
}
|
|
50315
50368
|
if (source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2") {
|
|
50316
50369
|
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))
|
|
50317
50370
|
throw new Error("Claude marketplace witnesses require an exact reviewed registry without synthetic changes");
|
|
50318
|
-
const sha2562 = (source.hashMode === "claude-marketplace-registry-v2" ? captureClaudeMarketplaceRegistryV2 : captureClaudeMarketplaceRegistry)(source.path,
|
|
50371
|
+
const sha2562 = (source.hashMode === "claude-marketplace-registry-v2" ? captureClaudeMarketplaceRegistryV2 : captureClaudeMarketplaceRegistry)(source.path, budget2).sha256;
|
|
50319
50372
|
if (sha2562 !== source.sha256)
|
|
50320
50373
|
throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
|
|
50321
50374
|
return sha2562;
|
|
@@ -50333,8 +50386,8 @@ function projected(source, changes, budget = discoveryByteBudget()) {
|
|
|
50333
50386
|
if (source.format !== undefined || source.fields !== undefined)
|
|
50334
50387
|
throw new Error("Raw discovery witnesses cannot project configuration fields");
|
|
50335
50388
|
if (source.hashMode === "path-bytes")
|
|
50336
|
-
return hashDiscoveryPathFile(source.path,
|
|
50337
|
-
return hashRawDiscoveryFile(source.path,
|
|
50389
|
+
return hashDiscoveryPathFile(source.path, budget2, changes);
|
|
50390
|
+
return hashRawDiscoveryFile(source.path, budget2, changes);
|
|
50338
50391
|
}
|
|
50339
50392
|
const text2 = read(source.path, changes);
|
|
50340
50393
|
if (text2 === null)
|
|
@@ -50466,7 +50519,7 @@ function verifyAgentDiscovery(binding, codexRecovery) {
|
|
|
50466
50519
|
verifyDiscoveryDirectories(projected2, installationRoots);
|
|
50467
50520
|
}
|
|
50468
50521
|
const absentRoots = [...absentCodexSkillRoots(binding), ...absentRetiredClaudeRoots(binding), ...retiredRoots.filter((root) => !lstatSync18(root, { throwIfNoEntry: false }))];
|
|
50469
|
-
const
|
|
50522
|
+
const budget2 = discoveryByteBudget();
|
|
50470
50523
|
for (const source of binding.sources) {
|
|
50471
50524
|
assertMarketplaceBinding(binding, source);
|
|
50472
50525
|
if (source.hashMode === "claude-plugin-registry" && binding.agent !== "claude")
|
|
@@ -50483,7 +50536,7 @@ function verifyAgentDiscovery(binding, codexRecovery) {
|
|
|
50483
50536
|
safe4(source.path);
|
|
50484
50537
|
continue;
|
|
50485
50538
|
}
|
|
50486
|
-
const current = projected(source, undefined,
|
|
50539
|
+
const current = projected(source, undefined, budget2);
|
|
50487
50540
|
if (current !== source.sha256 && !verifiesCodexHookDiscoverySource(binding, source, current, codexRecovery))
|
|
50488
50541
|
throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
|
|
50489
50542
|
}
|
|
@@ -50517,6 +50570,8 @@ function codexInstallationRoots(binding) {
|
|
|
50517
50570
|
});
|
|
50518
50571
|
}
|
|
50519
50572
|
function assertMarketplaceBinding(binding, source) {
|
|
50573
|
+
if (source.hashMode === "sumi-settings-v1" && (binding.agent !== "sumi" || binding.method !== "reviewed" || basename8(source.path) !== "sumi.json"))
|
|
50574
|
+
throw new Error("Sumi settings witnesses require explicit reviewed Sumi configuration");
|
|
50520
50575
|
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" || basename8(source.path) !== "config.toml"))
|
|
50521
50576
|
throw new Error("Codex settings witnesses require explicit reviewed Codex configuration");
|
|
50522
50577
|
if ((source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") && (binding.agent !== "claude" || binding.method !== "reviewed" || basename8(source.path) !== "settings.json"))
|
|
@@ -50541,7 +50596,7 @@ function resolveAgentDiscovery(options) {
|
|
|
50541
50596
|
if (agent === "hermes")
|
|
50542
50597
|
assertHermesEnvironment(home);
|
|
50543
50598
|
const configPath = agentDiscoveryConfigPath(home, agent);
|
|
50544
|
-
const configText = witness(configPath, agent === "hermes" ? "yaml" : agent === "codex" ? "toml" : "json", agent === "hermes" ? ["skills", "plugins", "hooks"] : agent === "claude" ? ["enabledPlugins", "extraKnownMarketplaces"] : agent === "codex" ? [...CODEX_DISCOVERY_PROJECTION_FIELDS] : agent === "gemini" ? ["skills", "extensions", "security"] : agent === "opencode" ? ["plugin", "skills"] : agent === "sumi" ? [
|
|
50599
|
+
const configText = witness(configPath, agent === "hermes" ? "yaml" : agent === "codex" ? "toml" : "json", agent === "hermes" ? ["skills", "plugins", "hooks"] : agent === "claude" ? ["enabledPlugins", "extraKnownMarketplaces"] : agent === "codex" ? [...CODEX_DISCOVERY_PROJECTION_FIELDS] : agent === "gemini" ? ["skills", "extensions", "security"] : agent === "opencode" ? ["plugin", "skills"] : agent === "sumi" ? [...SUMI_DISCOVERY_PROJECTION_FIELDS] : ["version"]);
|
|
50545
50600
|
const config2 = configText === null ? {} : agent === "hermes" ? parseHermesConfig(configText) : parseConfig(configText, configPath, agent === "codex");
|
|
50546
50601
|
const unresolved = (detail) => {
|
|
50547
50602
|
throw new Error(`Native discovery is unresolved (${agent}: ${detail}); provide a reviewed --discovery-inputs file`);
|
|
@@ -50638,9 +50693,9 @@ function resolveAgentDiscovery(options) {
|
|
|
50638
50693
|
verifyAgentDiscovery(retained);
|
|
50639
50694
|
if (!retained.sources.some((source) => source.path === canonical6(configPath) && source.format === undefined && source.fields === undefined))
|
|
50640
50695
|
unresolved("retained review is missing the full agent configuration source");
|
|
50641
|
-
if (retained.sources.some((source) => (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !== canonical6(configPath)))
|
|
50696
|
+
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 === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !== canonical6(configPath)))
|
|
50642
50697
|
unresolved("retained settings witness names another configuration source");
|
|
50643
|
-
const covered =
|
|
50698
|
+
const covered = supersedesSettingsProjection(agent, retained.sources, canonical6(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical6(configPath), source)) : sources;
|
|
50644
50699
|
if (covered.some((source) => !retained.sources.some((saved) => isDeepStrictEqual4(saved, source))) || [...roots].some((root) => !retained.roots.includes(root)) || agent === "gemini" && JSON.stringify(retained.builtinNames) !== JSON.stringify(builtinNames))
|
|
50645
50700
|
unresolved("retained review is missing current runtime discovery coverage");
|
|
50646
50701
|
return retained;
|
|
@@ -50655,11 +50710,11 @@ function resolveAgentDiscovery(options) {
|
|
|
50655
50710
|
if (review.sources.some((source) => source.format !== undefined || source.fields !== undefined))
|
|
50656
50711
|
throw new Error("Explicit discovery reviews require full source-file hashes");
|
|
50657
50712
|
verifyAgentDiscovery(supplied);
|
|
50658
|
-
if (review.sources.some((source) => (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !== canonical6(configPath)))
|
|
50659
|
-
throw new Error("Semantic settings witnesses must name the configured
|
|
50713
|
+
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 === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !== canonical6(configPath)))
|
|
50714
|
+
throw new Error("Semantic settings witnesses must name the configured agent configuration source");
|
|
50660
50715
|
if (!review.sources.some((source) => source.path === canonical6(configPath)))
|
|
50661
50716
|
throw new Error("Discovery review must include the agent configuration source");
|
|
50662
|
-
const reviewedSources =
|
|
50717
|
+
const reviewedSources = supersedesSettingsProjection(agent, review.sources, canonical6(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical6(configPath), source)) : sources;
|
|
50663
50718
|
return { ...supplied, roots: [...new Set([...roots, ...supplied.roots])].sort(), sources: [...reviewedSources, ...review.sources], ...agent === "gemini" ? { builtinNames } : {} };
|
|
50664
50719
|
}
|
|
50665
50720
|
function plugin(root) {
|
|
@@ -50776,6 +50831,7 @@ function resolveAgentDiscovery(options) {
|
|
|
50776
50831
|
}
|
|
50777
50832
|
var digest = (text2) => createHash16("sha256").update(text2).digest("hex");
|
|
50778
50833
|
var init_agent_discovery = __esm(() => {
|
|
50834
|
+
init_sumi_settings_witness();
|
|
50779
50835
|
init_agent_policy_limits();
|
|
50780
50836
|
init_agent_hermes();
|
|
50781
50837
|
init_agent_discovery_directories();
|
|
@@ -52077,7 +52133,7 @@ function parseRecurringResult(action, value, input2, identity3) {
|
|
|
52077
52133
|
}
|
|
52078
52134
|
return result;
|
|
52079
52135
|
}
|
|
52080
|
-
var RecurringInputError, RemoteRecurringUnavailableError, RemoteRecurringReadError, RemoteRecurringUnconfirmedError, failures, RemoteRecurringError, uuid3, instant2, integer2, digest2, list, inputs, capabilityNames,
|
|
52136
|
+
var RecurringInputError, RemoteRecurringUnavailableError, RemoteRecurringReadError, RemoteRecurringUnconfirmedError, failures, RemoteRecurringError, uuid3, instant2, integer2, digest2, list, inputs, capabilityNames, budget2, period, preview, consent, refusal2, occurrence, revocation, page = (item) => exports_external.object({ contractVersion: exports_external.literal(1), items: exports_external.array(item).max(100), nextCursor: exports_external.string().min(1).max(2048).nullable() }), results;
|
|
52081
52137
|
var init_remote_recurring = __esm(() => {
|
|
52082
52138
|
init_v4();
|
|
52083
52139
|
init_canonical_json();
|
|
@@ -52163,7 +52219,7 @@ var init_remote_recurring = __esm(() => {
|
|
|
52163
52219
|
occurrences: "recurring.occurrences",
|
|
52164
52220
|
revoke: "recurring.revoke"
|
|
52165
52221
|
};
|
|
52166
|
-
|
|
52222
|
+
budget2 = exports_external.object({ reservedCredits: integer2, settledCredits: integer2, admittedOccurrences: integer2 });
|
|
52167
52223
|
period = exports_external.object({ startsAt: instant2, endsAt: instant2 });
|
|
52168
52224
|
preview = exports_external.object({
|
|
52169
52225
|
contractVersion: exports_external.literal(1),
|
|
@@ -52185,8 +52241,8 @@ var init_remote_recurring = __esm(() => {
|
|
|
52185
52241
|
state: exports_external.enum(["active", "revoked", "expired"]),
|
|
52186
52242
|
activatedAt: instant2,
|
|
52187
52243
|
revokedAt: instant2.nullable(),
|
|
52188
|
-
total:
|
|
52189
|
-
currentPeriod:
|
|
52244
|
+
total: budget2,
|
|
52245
|
+
currentPeriod: budget2.extend(period.shape).nullable(),
|
|
52190
52246
|
nextDueAt: instant2.nullable()
|
|
52191
52247
|
});
|
|
52192
52248
|
refusal2 = exports_external.enum([
|
|
@@ -54144,7 +54200,7 @@ function checkedPublicationView(value, skillId, intentId, declaration) {
|
|
|
54144
54200
|
return invalid4();
|
|
54145
54201
|
return Object.freeze({ ...value });
|
|
54146
54202
|
}
|
|
54147
|
-
async function boundedJson(url2, init, token, mutation,
|
|
54203
|
+
async function boundedJson(url2, init, token, mutation, budget3 = 15000, signal) {
|
|
54148
54204
|
const controller = new AbortController;
|
|
54149
54205
|
let reader;
|
|
54150
54206
|
let response;
|
|
@@ -54199,7 +54255,7 @@ async function boundedJson(url2, init, token, mutation, budget2 = 15000, signal)
|
|
|
54199
54255
|
controller.abort();
|
|
54200
54256
|
reject(timeout);
|
|
54201
54257
|
};
|
|
54202
|
-
timer = setTimeout(abort, Math.max(1, Math.min(15000,
|
|
54258
|
+
timer = setTimeout(abort, Math.max(1, Math.min(15000, budget3)));
|
|
54203
54259
|
signal?.addEventListener("abort", abort, { once: true });
|
|
54204
54260
|
})]);
|
|
54205
54261
|
} catch (error61) {
|