@lousy-agents/mcp 5.13.5 → 5.14.0
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/dist/{27.js → 475.js} +6 -6
- package/dist/mcp-server.js +749 -367
- package/package.json +1 -1
package/dist/mcp-server.js
CHANGED
|
@@ -3333,7 +3333,7 @@ class Ajv {
|
|
|
3333
3333
|
constructor(opts = {}) {
|
|
3334
3334
|
this.schemas = {};
|
|
3335
3335
|
this.refs = {};
|
|
3336
|
-
this.formats =
|
|
3336
|
+
this.formats = Object.create(null);
|
|
3337
3337
|
this._compilations = new Set();
|
|
3338
3338
|
this._loading = {};
|
|
3339
3339
|
this._cache = new Map();
|
|
@@ -6559,7 +6559,7 @@ function escapeJsonPtr(str) {
|
|
|
6559
6559
|
|
|
6560
6560
|
|
|
6561
6561
|
},
|
|
6562
|
-
|
|
6562
|
+
8050(__unused_rspack_module, __unused_rspack___webpack_exports__, __webpack_require__) {
|
|
6563
6563
|
// NAMESPACE OBJECT: ../../node_modules/micromark/lib/constructs.js
|
|
6564
6564
|
var constructs_namespaceObject = {};
|
|
6565
6565
|
__webpack_require__.r(constructs_namespaceObject);
|
|
@@ -26562,7 +26562,7 @@ function isPathWithinRoot(rootPath, candidatePath) {
|
|
|
26562
26562
|
}
|
|
26563
26563
|
/**
|
|
26564
26564
|
* Ensures existing path segments under targetDir are not symbolic links.
|
|
26565
|
-
*/ async function
|
|
26565
|
+
*/ async function file_system_utils_assertPathHasNoSymbolicLinks(targetDir, absolutePath) {
|
|
26566
26566
|
const rootPath = await (0,promises_.realpath)(targetDir);
|
|
26567
26567
|
if (!isPathWithinRoot(rootPath, absolutePath)) {
|
|
26568
26568
|
throw new Error(`Resolved path is outside target directory: ${absolutePath}`);
|
|
@@ -26592,7 +26592,7 @@ function isPathWithinRoot(rootPath, candidatePath) {
|
|
|
26592
26592
|
* Resolves a relative path under targetDir and validates it does not pass through symlinks.
|
|
26593
26593
|
*/ async function file_system_utils_resolveSafePath(targetDir, relativePath) {
|
|
26594
26594
|
const resolvedPath = await resolvePathWithinRoot(targetDir, relativePath);
|
|
26595
|
-
await
|
|
26595
|
+
await file_system_utils_assertPathHasNoSymbolicLinks(targetDir, resolvedPath);
|
|
26596
26596
|
return resolvedPath;
|
|
26597
26597
|
}
|
|
26598
26598
|
/**
|
|
@@ -26778,14 +26778,14 @@ const _DRIVE_LETTER_RE = /^[A-Za-z]:$/;
|
|
|
26778
26778
|
const _ROOT_FOLDER_RE = /^\/([A-Za-z]:)?$/;
|
|
26779
26779
|
const _EXTNAME_RE = /.(\.[^./]+|\.)$/;
|
|
26780
26780
|
const _PATH_ROOT_RE = /^[/\\]|^[a-zA-Z]:[/\\]/;
|
|
26781
|
-
const
|
|
26781
|
+
const pathe_M_eThtNZ_sep = "/";
|
|
26782
26782
|
const normalize = function(path) {
|
|
26783
26783
|
if (path.length === 0) {
|
|
26784
26784
|
return ".";
|
|
26785
26785
|
}
|
|
26786
26786
|
path = normalizeWindowsPath(path);
|
|
26787
26787
|
const isUNCPath = path.match(_UNC_REGEX);
|
|
26788
|
-
const isPathAbsolute =
|
|
26788
|
+
const isPathAbsolute = pathe_M_eThtNZ_isAbsolute(path);
|
|
26789
26789
|
const trailingSeparator = path[path.length - 1] === "/";
|
|
26790
26790
|
path = normalizeString(path, !isPathAbsolute);
|
|
26791
26791
|
if (path.length === 0) {
|
|
@@ -26806,7 +26806,7 @@ const normalize = function(path) {
|
|
|
26806
26806
|
}
|
|
26807
26807
|
return `//${path}`;
|
|
26808
26808
|
}
|
|
26809
|
-
return isPathAbsolute && !
|
|
26809
|
+
return isPathAbsolute && !pathe_M_eThtNZ_isAbsolute(path) ? `/${path}` : path;
|
|
26810
26810
|
};
|
|
26811
26811
|
const pathe_M_eThtNZ_join = function(...segments) {
|
|
26812
26812
|
let path = "";
|
|
@@ -26845,10 +26845,10 @@ const pathe_M_eThtNZ_resolve = function(...arguments_) {
|
|
|
26845
26845
|
continue;
|
|
26846
26846
|
}
|
|
26847
26847
|
resolvedPath = `${path}/${resolvedPath}`;
|
|
26848
|
-
resolvedAbsolute =
|
|
26848
|
+
resolvedAbsolute = pathe_M_eThtNZ_isAbsolute(path);
|
|
26849
26849
|
}
|
|
26850
26850
|
resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute);
|
|
26851
|
-
if (resolvedAbsolute && !
|
|
26851
|
+
if (resolvedAbsolute && !pathe_M_eThtNZ_isAbsolute(resolvedPath)) {
|
|
26852
26852
|
return `/${resolvedPath}`;
|
|
26853
26853
|
}
|
|
26854
26854
|
return resolvedPath.length > 0 ? resolvedPath : ".";
|
|
@@ -26912,7 +26912,7 @@ function normalizeString(path, allowAboveRoot) {
|
|
|
26912
26912
|
}
|
|
26913
26913
|
return res;
|
|
26914
26914
|
}
|
|
26915
|
-
const
|
|
26915
|
+
const pathe_M_eThtNZ_isAbsolute = function(p) {
|
|
26916
26916
|
return _IS_ABSOLUTE_RE.test(p);
|
|
26917
26917
|
};
|
|
26918
26918
|
const toNamespacedPath = function(p) {
|
|
@@ -26923,7 +26923,7 @@ const pathe_M_eThtNZ_extname = function(p) {
|
|
|
26923
26923
|
const match = _EXTNAME_RE.exec(normalizeWindowsPath(p));
|
|
26924
26924
|
return match && match[1] || "";
|
|
26925
26925
|
};
|
|
26926
|
-
const
|
|
26926
|
+
const pathe_M_eThtNZ_relative = function(from, to) {
|
|
26927
26927
|
const _from = pathe_M_eThtNZ_resolve(from).replace(_ROOT_FOLDER_RE, "$1").split("/");
|
|
26928
26928
|
const _to = pathe_M_eThtNZ_resolve(to).replace(_ROOT_FOLDER_RE, "$1").split("/");
|
|
26929
26929
|
if (_to[0][1] === ":" && _from[0][1] === ":" && _from[0] !== _to[0]) {
|
|
@@ -26944,7 +26944,7 @@ const pathe_M_eThtNZ_dirname = function(p) {
|
|
|
26944
26944
|
if (segments.length === 1 && _DRIVE_LETTER_RE.test(segments[0])) {
|
|
26945
26945
|
segments[0] += "/";
|
|
26946
26946
|
}
|
|
26947
|
-
return segments.join("/") || (
|
|
26947
|
+
return segments.join("/") || (pathe_M_eThtNZ_isAbsolute(p) ? "/" : ".");
|
|
26948
26948
|
};
|
|
26949
26949
|
const pathe_M_eThtNZ_format = function(p) {
|
|
26950
26950
|
const ext = p.ext ? p.ext.startsWith(".") ? p.ext : `.${p.ext}` : "";
|
|
@@ -26989,15 +26989,15 @@ const pathe_M_eThtNZ_path = (/* unused pure expression or super */ null && ({
|
|
|
26989
26989
|
dirname: pathe_M_eThtNZ_dirname,
|
|
26990
26990
|
extname: pathe_M_eThtNZ_extname,
|
|
26991
26991
|
format: pathe_M_eThtNZ_format,
|
|
26992
|
-
isAbsolute:
|
|
26992
|
+
isAbsolute: pathe_M_eThtNZ_isAbsolute,
|
|
26993
26993
|
join: pathe_M_eThtNZ_join,
|
|
26994
26994
|
matchesGlob: matchesGlob,
|
|
26995
26995
|
normalize: normalize,
|
|
26996
26996
|
normalizeString: normalizeString,
|
|
26997
26997
|
parse: pathe_M_eThtNZ_parse,
|
|
26998
|
-
relative:
|
|
26998
|
+
relative: pathe_M_eThtNZ_relative,
|
|
26999
26999
|
resolve: pathe_M_eThtNZ_resolve,
|
|
27000
|
-
sep:
|
|
27000
|
+
sep: pathe_M_eThtNZ_sep,
|
|
27001
27001
|
toNamespacedPath: toNamespacedPath
|
|
27002
27002
|
}));
|
|
27003
27003
|
|
|
@@ -28502,371 +28502,317 @@ var jsonc = __webpack_require__(5975);
|
|
|
28502
28502
|
|
|
28503
28503
|
|
|
28504
28504
|
|
|
28505
|
-
|
|
28506
28505
|
const defaultFindOptions = {
|
|
28507
|
-
|
|
28508
|
-
|
|
28509
|
-
|
|
28510
|
-
|
|
28511
|
-
|
|
28512
|
-
|
|
28513
|
-
|
|
28514
|
-
|
|
28515
|
-
} catch {
|
|
28516
|
-
}
|
|
28517
|
-
}
|
|
28506
|
+
startingFrom: ".",
|
|
28507
|
+
rootPattern: /^node_modules$/,
|
|
28508
|
+
reverse: false,
|
|
28509
|
+
test: (filePath) => {
|
|
28510
|
+
try {
|
|
28511
|
+
if ((0,external_node_fs_.statSync)(filePath).isFile()) return true;
|
|
28512
|
+
} catch {}
|
|
28513
|
+
}
|
|
28518
28514
|
};
|
|
28519
28515
|
async function findFile(filename, _options = {}) {
|
|
28520
|
-
|
|
28521
|
-
|
|
28522
|
-
|
|
28523
|
-
|
|
28524
|
-
|
|
28525
|
-
|
|
28526
|
-
|
|
28527
|
-
|
|
28528
|
-
|
|
28529
|
-
|
|
28530
|
-
|
|
28531
|
-
|
|
28532
|
-
|
|
28533
|
-
|
|
28534
|
-
|
|
28535
|
-
|
|
28536
|
-
|
|
28537
|
-
|
|
28538
|
-
|
|
28539
|
-
|
|
28540
|
-
|
|
28541
|
-
}
|
|
28542
|
-
}
|
|
28543
|
-
}
|
|
28544
|
-
} else {
|
|
28545
|
-
for (let index = segments.length; index > root; index--) {
|
|
28546
|
-
for (const filename2 of filenames) {
|
|
28547
|
-
const filePath = pathe_M_eThtNZ_join(...segments.slice(0, index), filename2);
|
|
28548
|
-
if (await options.test(filePath)) {
|
|
28549
|
-
return filePath;
|
|
28550
|
-
}
|
|
28551
|
-
}
|
|
28552
|
-
}
|
|
28553
|
-
}
|
|
28554
|
-
throw new Error(
|
|
28555
|
-
`Cannot find matching ${filename} in ${options.startingFrom} or parent directories`
|
|
28556
|
-
);
|
|
28516
|
+
const filenames = Array.isArray(filename) ? filename : [filename];
|
|
28517
|
+
const options = {
|
|
28518
|
+
...defaultFindOptions,
|
|
28519
|
+
..._options
|
|
28520
|
+
};
|
|
28521
|
+
const basePath = pathe_M_eThtNZ_resolve(options.startingFrom);
|
|
28522
|
+
const leadingSlash = basePath[0] === "/";
|
|
28523
|
+
const segments = basePath.split("/").filter(Boolean);
|
|
28524
|
+
if (filenames.includes(segments.at(-1)) && await options.test(basePath)) return basePath;
|
|
28525
|
+
if (leadingSlash) segments[0] = "/" + segments[0];
|
|
28526
|
+
let root = segments.findIndex((r) => r.match(options.rootPattern));
|
|
28527
|
+
if (root === -1) root = 0;
|
|
28528
|
+
if (options.reverse) for (let index = root + 1; index <= segments.length; index++) for (const filename of filenames) {
|
|
28529
|
+
const filePath = pathe_M_eThtNZ_join(...segments.slice(0, index), filename);
|
|
28530
|
+
if (await options.test(filePath)) return filePath;
|
|
28531
|
+
}
|
|
28532
|
+
else for (let index = segments.length; index > root; index--) for (const filename of filenames) {
|
|
28533
|
+
const filePath = pathe_M_eThtNZ_join(...segments.slice(0, index), filename);
|
|
28534
|
+
if (await options.test(filePath)) return filePath;
|
|
28535
|
+
}
|
|
28536
|
+
throw new Error(`Cannot find matching ${filename} in ${options.startingFrom} or parent directories`);
|
|
28557
28537
|
}
|
|
28558
28538
|
function findNearestFile(filename, options = {}) {
|
|
28559
|
-
|
|
28539
|
+
return findFile(filename, options);
|
|
28560
28540
|
}
|
|
28561
28541
|
function findFarthestFile(filename, options = {}) {
|
|
28562
|
-
|
|
28542
|
+
return findFile(filename, {
|
|
28543
|
+
...options,
|
|
28544
|
+
reverse: true
|
|
28545
|
+
});
|
|
28563
28546
|
}
|
|
28564
|
-
|
|
28565
28547
|
function _resolvePath(id, opts = {}) {
|
|
28566
|
-
|
|
28567
|
-
|
|
28568
|
-
|
|
28569
|
-
|
|
28570
|
-
|
|
28571
|
-
|
|
28572
|
-
return resolveModulePath(id, {
|
|
28573
|
-
...opts,
|
|
28574
|
-
from: opts.from || opts.parent || opts.url
|
|
28575
|
-
});
|
|
28548
|
+
if (id instanceof URL || id.startsWith("file://")) return normalize((0,external_node_url_.fileURLToPath)(id));
|
|
28549
|
+
if (pathe_M_eThtNZ_isAbsolute(id)) return normalize(id);
|
|
28550
|
+
return resolveModulePath(id, {
|
|
28551
|
+
...opts,
|
|
28552
|
+
from: opts.from || opts.parent || opts.url
|
|
28553
|
+
});
|
|
28576
28554
|
}
|
|
28577
|
-
|
|
28578
28555
|
const FileCache$1 = /* @__PURE__ */ (/* unused pure expression or super */ null && (new Map()));
|
|
28579
28556
|
function defineTSConfig(tsconfig) {
|
|
28580
|
-
|
|
28557
|
+
return tsconfig;
|
|
28581
28558
|
}
|
|
28582
28559
|
async function readTSConfig(id, options = {}) {
|
|
28583
|
-
|
|
28584
|
-
|
|
28585
|
-
|
|
28586
|
-
|
|
28587
|
-
|
|
28588
|
-
|
|
28589
|
-
const parsed = parseJSONC(text);
|
|
28590
|
-
cache.set(resolvedPath, parsed);
|
|
28591
|
-
return parsed;
|
|
28560
|
+
const resolvedPath = await resolveTSConfig(id, options);
|
|
28561
|
+
const cache = options.cache && typeof options.cache !== "boolean" ? options.cache : FileCache$1;
|
|
28562
|
+
if (options.cache && cache.has(resolvedPath)) return cache.get(resolvedPath);
|
|
28563
|
+
const parsed = parseJSONC(await promises.readFile(resolvedPath, "utf8"));
|
|
28564
|
+
cache.set(resolvedPath, parsed);
|
|
28565
|
+
return parsed;
|
|
28592
28566
|
}
|
|
28593
28567
|
async function writeTSConfig(path, tsconfig) {
|
|
28594
|
-
|
|
28568
|
+
await promises.writeFile(path, stringifyJSONC(tsconfig));
|
|
28595
28569
|
}
|
|
28596
28570
|
async function resolveTSConfig(id = process.cwd(), options = {}) {
|
|
28597
|
-
|
|
28598
|
-
|
|
28599
|
-
|
|
28600
|
-
|
|
28571
|
+
return findNearestFile("tsconfig.json", {
|
|
28572
|
+
...options,
|
|
28573
|
+
startingFrom: _resolvePath(id, options)
|
|
28574
|
+
});
|
|
28601
28575
|
}
|
|
28602
|
-
|
|
28603
28576
|
const lockFiles = [
|
|
28604
|
-
|
|
28605
|
-
|
|
28606
|
-
|
|
28607
|
-
|
|
28608
|
-
|
|
28609
|
-
|
|
28610
|
-
|
|
28577
|
+
"yarn.lock",
|
|
28578
|
+
"package-lock.json",
|
|
28579
|
+
"pnpm-lock.yaml",
|
|
28580
|
+
"npm-shrinkwrap.json",
|
|
28581
|
+
"bun.lockb",
|
|
28582
|
+
"bun.lock",
|
|
28583
|
+
"deno.lock"
|
|
28584
|
+
];
|
|
28585
|
+
const packageFiles = [
|
|
28586
|
+
"package.json",
|
|
28587
|
+
"package.json5",
|
|
28588
|
+
"package.yaml"
|
|
28611
28589
|
];
|
|
28612
|
-
const packageFiles = ["package.json", "package.json5", "package.yaml"];
|
|
28613
28590
|
const workspaceFiles = [
|
|
28614
|
-
|
|
28615
|
-
|
|
28616
|
-
|
|
28617
|
-
|
|
28618
|
-
|
|
28619
|
-
|
|
28591
|
+
"pnpm-workspace.yaml",
|
|
28592
|
+
"lerna.json",
|
|
28593
|
+
"turbo.json",
|
|
28594
|
+
"rush.json",
|
|
28595
|
+
"deno.json",
|
|
28596
|
+
"deno.jsonc"
|
|
28620
28597
|
];
|
|
28621
28598
|
const FileCache = /* @__PURE__ */ new Map();
|
|
28622
28599
|
function definePackageJSON(pkg) {
|
|
28623
|
-
|
|
28600
|
+
return pkg;
|
|
28624
28601
|
}
|
|
28625
28602
|
async function findPackage(id = process.cwd(), options = {}) {
|
|
28626
|
-
|
|
28627
|
-
|
|
28628
|
-
|
|
28629
|
-
|
|
28603
|
+
return findNearestFile(packageFiles, {
|
|
28604
|
+
...options,
|
|
28605
|
+
startingFrom: _resolvePath(id, options)
|
|
28606
|
+
});
|
|
28630
28607
|
}
|
|
28631
28608
|
async function readPackage(id, options = {}) {
|
|
28632
|
-
|
|
28633
|
-
|
|
28634
|
-
|
|
28635
|
-
|
|
28636
|
-
|
|
28637
|
-
|
|
28638
|
-
|
|
28639
|
-
|
|
28640
|
-
|
|
28641
|
-
|
|
28642
|
-
|
|
28643
|
-
|
|
28644
|
-
|
|
28645
|
-
|
|
28646
|
-
} catch {
|
|
28647
|
-
parsed = parseJSONC(blob);
|
|
28648
|
-
}
|
|
28649
|
-
}
|
|
28650
|
-
cache.set(resolvedPath, parsed);
|
|
28651
|
-
return parsed;
|
|
28609
|
+
const resolvedPath = await findPackage(id, options);
|
|
28610
|
+
const cache = options.cache && typeof options.cache !== "boolean" ? options.cache : FileCache;
|
|
28611
|
+
if (options.cache && cache.has(resolvedPath)) return cache.get(resolvedPath);
|
|
28612
|
+
const blob = await promises.readFile(resolvedPath, "utf8");
|
|
28613
|
+
let parsed;
|
|
28614
|
+
if (resolvedPath.endsWith(".json5")) parsed = parseJSON5(blob);
|
|
28615
|
+
else if (resolvedPath.endsWith(".yaml")) parsed = parseYAML(blob);
|
|
28616
|
+
else try {
|
|
28617
|
+
parsed = parseJSON(blob);
|
|
28618
|
+
} catch {
|
|
28619
|
+
parsed = parseJSONC(blob);
|
|
28620
|
+
}
|
|
28621
|
+
cache.set(resolvedPath, parsed);
|
|
28622
|
+
return parsed;
|
|
28652
28623
|
}
|
|
28653
28624
|
async function writePackage(path, pkg) {
|
|
28654
|
-
|
|
28655
|
-
|
|
28656
|
-
|
|
28657
|
-
|
|
28658
|
-
|
|
28659
|
-
} else {
|
|
28660
|
-
content = stringifyJSON(pkg);
|
|
28661
|
-
}
|
|
28662
|
-
await promises.writeFile(path, content);
|
|
28625
|
+
let content;
|
|
28626
|
+
if (path.endsWith(".json5")) content = stringifyJSON5(pkg);
|
|
28627
|
+
else if (path.endsWith(".yaml")) content = stringifyYAML(pkg);
|
|
28628
|
+
else content = stringifyJSON(pkg);
|
|
28629
|
+
await promises.writeFile(path, content);
|
|
28663
28630
|
}
|
|
28664
28631
|
async function readPackageJSON(id, options = {}) {
|
|
28665
|
-
|
|
28666
|
-
|
|
28667
|
-
|
|
28668
|
-
|
|
28669
|
-
|
|
28670
|
-
|
|
28671
|
-
|
|
28672
|
-
|
|
28673
|
-
|
|
28674
|
-
|
|
28675
|
-
|
|
28676
|
-
|
|
28677
|
-
cache.set(resolvedPath, parsed);
|
|
28678
|
-
return parsed;
|
|
28632
|
+
const resolvedPath = await resolvePackageJSON(id, options);
|
|
28633
|
+
const cache = options.cache && typeof options.cache !== "boolean" ? options.cache : FileCache;
|
|
28634
|
+
if (options.cache && cache.has(resolvedPath)) return cache.get(resolvedPath);
|
|
28635
|
+
const blob = await external_node_fs_.promises.readFile(resolvedPath, "utf8");
|
|
28636
|
+
let parsed;
|
|
28637
|
+
try {
|
|
28638
|
+
parsed = json_n(blob);
|
|
28639
|
+
} catch {
|
|
28640
|
+
parsed = (0,jsonc.parseJSONC)(blob);
|
|
28641
|
+
}
|
|
28642
|
+
cache.set(resolvedPath, parsed);
|
|
28643
|
+
return parsed;
|
|
28679
28644
|
}
|
|
28680
28645
|
async function writePackageJSON(path, pkg) {
|
|
28681
|
-
|
|
28646
|
+
await promises.writeFile(path, stringifyJSON(pkg));
|
|
28682
28647
|
}
|
|
28683
28648
|
async function resolvePackageJSON(id = process.cwd(), options = {}) {
|
|
28684
|
-
|
|
28685
|
-
|
|
28686
|
-
|
|
28687
|
-
|
|
28649
|
+
return findNearestFile("package.json", {
|
|
28650
|
+
...options,
|
|
28651
|
+
startingFrom: _resolvePath(id, options)
|
|
28652
|
+
});
|
|
28688
28653
|
}
|
|
28689
28654
|
async function resolveLockfile(id = process.cwd(), options = {}) {
|
|
28690
|
-
|
|
28691
|
-
|
|
28692
|
-
|
|
28693
|
-
|
|
28655
|
+
return findNearestFile(lockFiles, {
|
|
28656
|
+
...options,
|
|
28657
|
+
startingFrom: _resolvePath(id, options)
|
|
28658
|
+
});
|
|
28694
28659
|
}
|
|
28695
28660
|
const workspaceTests = {
|
|
28696
|
-
|
|
28697
|
-
|
|
28698
|
-
|
|
28699
|
-
|
|
28661
|
+
workspaceFile: (opts) => findFile(workspaceFiles, opts).then((r) => pathe_M_eThtNZ_dirname(r)),
|
|
28662
|
+
gitConfig: (opts) => findFile(".git/config", opts).then((r) => pathe_M_eThtNZ_resolve(r, "../..")),
|
|
28663
|
+
lockFile: (opts) => findFile(lockFiles, opts).then((r) => pathe_M_eThtNZ_dirname(r)),
|
|
28664
|
+
packageJson: (opts) => findFile(packageFiles, opts).then((r) => pathe_M_eThtNZ_dirname(r))
|
|
28700
28665
|
};
|
|
28701
28666
|
async function findWorkspaceDir(id = process.cwd(), options = {}) {
|
|
28702
|
-
|
|
28703
|
-
|
|
28704
|
-
|
|
28705
|
-
|
|
28706
|
-
|
|
28707
|
-
|
|
28708
|
-
|
|
28709
|
-
|
|
28710
|
-
|
|
28711
|
-
|
|
28712
|
-
|
|
28713
|
-
|
|
28714
|
-
|
|
28715
|
-
|
|
28716
|
-
|
|
28717
|
-
|
|
28718
|
-
|
|
28719
|
-
|
|
28720
|
-
|
|
28667
|
+
const startingFrom = _resolvePath(id, options);
|
|
28668
|
+
const tests = options.tests || [
|
|
28669
|
+
"workspaceFile",
|
|
28670
|
+
"gitConfig",
|
|
28671
|
+
"lockFile",
|
|
28672
|
+
"packageJson"
|
|
28673
|
+
];
|
|
28674
|
+
for (const testName of tests) {
|
|
28675
|
+
const test = workspaceTests[testName];
|
|
28676
|
+
if (options[testName] === false || !test) continue;
|
|
28677
|
+
const direction = options[testName] || (testName === "gitConfig" ? "closest" : "furthest");
|
|
28678
|
+
const detected = await test({
|
|
28679
|
+
...options,
|
|
28680
|
+
startingFrom,
|
|
28681
|
+
reverse: direction === "furthest"
|
|
28682
|
+
}).catch(() => {});
|
|
28683
|
+
if (detected) return detected;
|
|
28684
|
+
}
|
|
28685
|
+
throw new Error(`Cannot detect workspace root from ${id}`);
|
|
28721
28686
|
}
|
|
28722
28687
|
async function updatePackage(id, callback, options = {}) {
|
|
28723
|
-
|
|
28724
|
-
|
|
28725
|
-
|
|
28726
|
-
|
|
28727
|
-
|
|
28728
|
-
|
|
28729
|
-
}
|
|
28730
|
-
return Reflect.get(target, prop);
|
|
28731
|
-
}
|
|
28732
|
-
});
|
|
28733
|
-
const updated = await callback(proxy) || pkg;
|
|
28734
|
-
await writePackage(resolvedPath, updated);
|
|
28688
|
+
const resolvedPath = await findPackage(id, options);
|
|
28689
|
+
const pkg = await readPackage(id, options);
|
|
28690
|
+
await writePackage(resolvedPath, await callback(new Proxy(pkg, { get(target, prop) {
|
|
28691
|
+
if (typeof prop === "string" && objectKeys.has(prop) && !Object.hasOwn(target, prop)) target[prop] = {};
|
|
28692
|
+
return Reflect.get(target, prop);
|
|
28693
|
+
} })) || pkg);
|
|
28735
28694
|
}
|
|
28736
28695
|
function sortPackage(pkg) {
|
|
28737
|
-
|
|
28738
|
-
|
|
28739
|
-
|
|
28740
|
-
|
|
28741
|
-
|
|
28742
|
-
|
|
28743
|
-
|
|
28744
|
-
|
|
28745
|
-
|
|
28746
|
-
|
|
28747
|
-
|
|
28748
|
-
|
|
28749
|
-
|
|
28750
|
-
|
|
28751
|
-
|
|
28752
|
-
|
|
28753
|
-
|
|
28754
|
-
|
|
28755
|
-
|
|
28756
|
-
const value = sorted[key];
|
|
28757
|
-
if (dist_isObject(value)) {
|
|
28758
|
-
sorted[key] = sortObject(value);
|
|
28759
|
-
}
|
|
28760
|
-
}
|
|
28761
|
-
return sorted;
|
|
28696
|
+
const sorted = {};
|
|
28697
|
+
const originalKeys = Object.keys(pkg);
|
|
28698
|
+
const knownKeysPresent = defaultFieldOrder.filter((key) => Object.hasOwn(pkg, key));
|
|
28699
|
+
for (const key of originalKeys) {
|
|
28700
|
+
const currentIndex = knownKeysPresent.indexOf(key);
|
|
28701
|
+
if (currentIndex === -1) {
|
|
28702
|
+
sorted[key] = pkg[key];
|
|
28703
|
+
continue;
|
|
28704
|
+
}
|
|
28705
|
+
for (let i = 0; i <= currentIndex; i++) {
|
|
28706
|
+
const knownKey = knownKeysPresent[i];
|
|
28707
|
+
if (!Object.hasOwn(sorted, knownKey)) sorted[knownKey] = pkg[knownKey];
|
|
28708
|
+
}
|
|
28709
|
+
}
|
|
28710
|
+
for (const key of [...dependencyKeys, "scripts"]) {
|
|
28711
|
+
const value = sorted[key];
|
|
28712
|
+
if (dist_isObject(value)) sorted[key] = sortObject(value);
|
|
28713
|
+
}
|
|
28714
|
+
return sorted;
|
|
28762
28715
|
}
|
|
28763
28716
|
function normalizePackage(pkg) {
|
|
28764
|
-
|
|
28765
|
-
|
|
28766
|
-
|
|
28767
|
-
|
|
28768
|
-
|
|
28769
|
-
|
|
28770
|
-
|
|
28771
|
-
delete normalized[key];
|
|
28772
|
-
}
|
|
28773
|
-
}
|
|
28774
|
-
return normalized;
|
|
28717
|
+
const normalized = sortPackage(pkg);
|
|
28718
|
+
for (const key of dependencyKeys) {
|
|
28719
|
+
if (!Object.hasOwn(normalized, key)) continue;
|
|
28720
|
+
const value = normalized[key];
|
|
28721
|
+
if (!dist_isObject(value)) delete normalized[key];
|
|
28722
|
+
}
|
|
28723
|
+
return normalized;
|
|
28775
28724
|
}
|
|
28776
28725
|
function dist_isObject(value) {
|
|
28777
|
-
|
|
28726
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
28778
28727
|
}
|
|
28779
28728
|
function sortObject(obj) {
|
|
28780
|
-
|
|
28781
|
-
Object.entries(obj).sort(([a], [b]) => a.localeCompare(b))
|
|
28782
|
-
);
|
|
28729
|
+
return Object.fromEntries(Object.entries(obj).sort(([a], [b]) => a.localeCompare(b)));
|
|
28783
28730
|
}
|
|
28784
28731
|
const dependencyKeys = (/* unused pure expression or super */ null && ([
|
|
28785
|
-
|
|
28786
|
-
|
|
28787
|
-
|
|
28788
|
-
|
|
28732
|
+
"dependencies",
|
|
28733
|
+
"devDependencies",
|
|
28734
|
+
"optionalDependencies",
|
|
28735
|
+
"peerDependencies"
|
|
28789
28736
|
]));
|
|
28790
|
-
const objectKeys =
|
|
28791
|
-
|
|
28792
|
-
|
|
28793
|
-
|
|
28794
|
-
|
|
28795
|
-
|
|
28796
|
-
|
|
28797
|
-
|
|
28798
|
-
|
|
28799
|
-
|
|
28800
|
-
|
|
28801
|
-
|
|
28802
|
-
|
|
28803
|
-
])
|
|
28737
|
+
const objectKeys = new Set([
|
|
28738
|
+
"typesVersions",
|
|
28739
|
+
"scripts",
|
|
28740
|
+
"resolutions",
|
|
28741
|
+
"overrides",
|
|
28742
|
+
"dependencies",
|
|
28743
|
+
"devDependencies",
|
|
28744
|
+
"dependenciesMeta",
|
|
28745
|
+
"peerDependencies",
|
|
28746
|
+
"peerDependenciesMeta",
|
|
28747
|
+
"optionalDependencies",
|
|
28748
|
+
"engines",
|
|
28749
|
+
"publishConfig"
|
|
28750
|
+
]);
|
|
28804
28751
|
const defaultFieldOrder = (/* unused pure expression or super */ null && ([
|
|
28805
|
-
|
|
28806
|
-
|
|
28807
|
-
|
|
28808
|
-
|
|
28809
|
-
|
|
28810
|
-
|
|
28811
|
-
|
|
28812
|
-
|
|
28813
|
-
|
|
28814
|
-
|
|
28815
|
-
|
|
28816
|
-
|
|
28817
|
-
|
|
28818
|
-
|
|
28819
|
-
|
|
28820
|
-
|
|
28821
|
-
|
|
28822
|
-
|
|
28823
|
-
|
|
28824
|
-
|
|
28825
|
-
|
|
28826
|
-
|
|
28827
|
-
|
|
28828
|
-
|
|
28829
|
-
|
|
28830
|
-
|
|
28831
|
-
|
|
28832
|
-
|
|
28833
|
-
|
|
28834
|
-
|
|
28835
|
-
|
|
28836
|
-
|
|
28837
|
-
|
|
28838
|
-
|
|
28839
|
-
|
|
28840
|
-
|
|
28841
|
-
|
|
28842
|
-
|
|
28843
|
-
|
|
28844
|
-
|
|
28752
|
+
"$schema",
|
|
28753
|
+
"name",
|
|
28754
|
+
"version",
|
|
28755
|
+
"private",
|
|
28756
|
+
"description",
|
|
28757
|
+
"keywords",
|
|
28758
|
+
"homepage",
|
|
28759
|
+
"bugs",
|
|
28760
|
+
"repository",
|
|
28761
|
+
"funding",
|
|
28762
|
+
"license",
|
|
28763
|
+
"author",
|
|
28764
|
+
"sideEffects",
|
|
28765
|
+
"type",
|
|
28766
|
+
"imports",
|
|
28767
|
+
"exports",
|
|
28768
|
+
"main",
|
|
28769
|
+
"module",
|
|
28770
|
+
"browser",
|
|
28771
|
+
"types",
|
|
28772
|
+
"typesVersions",
|
|
28773
|
+
"typings",
|
|
28774
|
+
"bin",
|
|
28775
|
+
"man",
|
|
28776
|
+
"files",
|
|
28777
|
+
"workspaces",
|
|
28778
|
+
"scripts",
|
|
28779
|
+
"resolutions",
|
|
28780
|
+
"overrides",
|
|
28781
|
+
"dependencies",
|
|
28782
|
+
"devDependencies",
|
|
28783
|
+
"dependenciesMeta",
|
|
28784
|
+
"peerDependencies",
|
|
28785
|
+
"peerDependenciesMeta",
|
|
28786
|
+
"optionalDependencies",
|
|
28787
|
+
"bundledDependencies",
|
|
28788
|
+
"bundleDependencies",
|
|
28789
|
+
"packageManager",
|
|
28790
|
+
"engines",
|
|
28791
|
+
"publishConfig"
|
|
28845
28792
|
]));
|
|
28846
|
-
|
|
28847
28793
|
function defineGitConfig(config) {
|
|
28848
|
-
|
|
28794
|
+
return config;
|
|
28849
28795
|
}
|
|
28850
28796
|
async function resolveGitConfig(dir, opts) {
|
|
28851
|
-
|
|
28797
|
+
return findNearestFile(".git/config", {
|
|
28798
|
+
...opts,
|
|
28799
|
+
startingFrom: dir
|
|
28800
|
+
});
|
|
28852
28801
|
}
|
|
28853
28802
|
async function readGitConfig(dir, opts) {
|
|
28854
|
-
|
|
28855
|
-
const ini = await readFile(path, "utf8");
|
|
28856
|
-
return parseGitConfig(ini);
|
|
28803
|
+
return parseGitConfig(await readFile(await resolveGitConfig(dir, opts), "utf8"));
|
|
28857
28804
|
}
|
|
28858
28805
|
async function writeGitConfig(path, config) {
|
|
28859
|
-
|
|
28806
|
+
await writeFile(path, stringifyGitConfig(config));
|
|
28860
28807
|
}
|
|
28861
28808
|
function parseGitConfig(ini) {
|
|
28862
|
-
|
|
28809
|
+
return parseINI(ini.replaceAll(/^\[(\w+) "(.+)"\]$/gm, "[$1.$2]"));
|
|
28863
28810
|
}
|
|
28864
28811
|
function stringifyGitConfig(config) {
|
|
28865
|
-
|
|
28812
|
+
return stringifyINI(config).replaceAll(/^\[(\w+)\.(\w+)\]$/gm, "[$1 \"$2\"]");
|
|
28866
28813
|
}
|
|
28867
28814
|
|
|
28868
28815
|
|
|
28869
|
-
|
|
28870
28816
|
;// CONCATENATED MODULE: ../../node_modules/c12/dist/index.mjs
|
|
28871
28817
|
|
|
28872
28818
|
|
|
@@ -29237,7 +29183,7 @@ async function watchConfig(options) {
|
|
|
29237
29183
|
options.rcFile && resolve(l.cwd, typeof options.rcFile === "string" ? options.rcFile : `.${configName}rc`),
|
|
29238
29184
|
options.packageJson && resolve(l.cwd, "package.json")
|
|
29239
29185
|
]).filter(Boolean))];
|
|
29240
|
-
const watch = await __webpack_require__.e(/* import() */
|
|
29186
|
+
const watch = await __webpack_require__.e(/* import() */ 475).then(__webpack_require__.bind(__webpack_require__, 4710)).then((r) => r.watch || r.default || r);
|
|
29241
29187
|
const { diff } = await __webpack_require__.e(/* import() */ 164).then(__webpack_require__.bind(__webpack_require__, 263));
|
|
29242
29188
|
const _fswatcher = watch(watchingFiles, {
|
|
29243
29189
|
ignoreInitial: true,
|
|
@@ -29990,6 +29936,240 @@ function defaultExec(command, args, options) {
|
|
|
29990
29936
|
return new OctokitRulesetGateway(octokit);
|
|
29991
29937
|
}
|
|
29992
29938
|
|
|
29939
|
+
// EXTERNAL MODULE: external "node:crypto"
|
|
29940
|
+
var external_node_crypto_ = __webpack_require__(7598);
|
|
29941
|
+
;// CONCATENATED MODULE: ../core/src/gateways/init-hooks-config-gateway.ts
|
|
29942
|
+
|
|
29943
|
+
|
|
29944
|
+
|
|
29945
|
+
|
|
29946
|
+
|
|
29947
|
+
const CLAUDE_SETTINGS_PATH = (0,external_node_path_.join)(".claude", "settings.json");
|
|
29948
|
+
/**
|
|
29949
|
+
* PreToolUse hooks for Edit and Write tools only.
|
|
29950
|
+
* File paths are NOT passed as shell arguments — Claude Code pipes the hook
|
|
29951
|
+
* JSON (including tool_input.file_path) to the command via stdin.
|
|
29952
|
+
*/ const PRE_TOOL_USE_HOOKS = [
|
|
29953
|
+
{
|
|
29954
|
+
matcher: "Edit",
|
|
29955
|
+
hooks: [
|
|
29956
|
+
{
|
|
29957
|
+
type: "command",
|
|
29958
|
+
command: "lousy-agents context"
|
|
29959
|
+
}
|
|
29960
|
+
]
|
|
29961
|
+
},
|
|
29962
|
+
{
|
|
29963
|
+
matcher: "Write",
|
|
29964
|
+
hooks: [
|
|
29965
|
+
{
|
|
29966
|
+
type: "command",
|
|
29967
|
+
command: "lousy-agents context"
|
|
29968
|
+
}
|
|
29969
|
+
]
|
|
29970
|
+
}
|
|
29971
|
+
];
|
|
29972
|
+
const SESSION_START_HOOKS = [
|
|
29973
|
+
{
|
|
29974
|
+
hooks: [
|
|
29975
|
+
{
|
|
29976
|
+
type: "command",
|
|
29977
|
+
command: "lousy-agents context"
|
|
29978
|
+
}
|
|
29979
|
+
]
|
|
29980
|
+
}
|
|
29981
|
+
];
|
|
29982
|
+
const STOP_HOOKS = [
|
|
29983
|
+
{
|
|
29984
|
+
hooks: [
|
|
29985
|
+
{
|
|
29986
|
+
type: "command",
|
|
29987
|
+
command: "lousy-agents capture"
|
|
29988
|
+
}
|
|
29989
|
+
]
|
|
29990
|
+
}
|
|
29991
|
+
];
|
|
29992
|
+
const SUBAGENT_STOP_HOOKS = [
|
|
29993
|
+
{
|
|
29994
|
+
hooks: [
|
|
29995
|
+
{
|
|
29996
|
+
type: "command",
|
|
29997
|
+
command: "lousy-agents capture"
|
|
29998
|
+
}
|
|
29999
|
+
]
|
|
30000
|
+
}
|
|
30001
|
+
];
|
|
30002
|
+
const DANGEROUS_KEYS = new Set([
|
|
30003
|
+
"__proto__",
|
|
30004
|
+
"constructor",
|
|
30005
|
+
"prototype"
|
|
30006
|
+
]);
|
|
30007
|
+
function hasPrototypePollutionKey(obj, depth = 0) {
|
|
30008
|
+
if (depth > 20) return false;
|
|
30009
|
+
if (obj === null || typeof obj !== "object") return false;
|
|
30010
|
+
for (const key of Object.keys(obj)){
|
|
30011
|
+
if (DANGEROUS_KEYS.has(key)) return true;
|
|
30012
|
+
if (hasPrototypePollutionKey(obj[key], depth + 1)) return true;
|
|
30013
|
+
}
|
|
30014
|
+
return false;
|
|
30015
|
+
}
|
|
30016
|
+
function safeJoin(rootDir, relativePath) {
|
|
30017
|
+
const resolved = resolve(rootDir, relativePath);
|
|
30018
|
+
const root = resolve(rootDir);
|
|
30019
|
+
if (resolved !== root) {
|
|
30020
|
+
const rel = relative(root, resolved);
|
|
30021
|
+
if (rel === ".." || rel.startsWith(`..${sep}`) || isAbsolute(rel)) {
|
|
30022
|
+
throw new Error(`Resolved path is outside target directory: ${relativePath}`);
|
|
30023
|
+
}
|
|
30024
|
+
}
|
|
30025
|
+
return resolved;
|
|
30026
|
+
}
|
|
30027
|
+
function getExistingMatchers(hooks, event) {
|
|
30028
|
+
const entries = hooks[event];
|
|
30029
|
+
if (!Array.isArray(entries)) return new Set();
|
|
30030
|
+
return new Set(entries.filter((e)=>e !== null && typeof e === "object").map((e)=>e.matcher).filter((m)=>typeof m === "string"));
|
|
30031
|
+
}
|
|
30032
|
+
class InitHooksConfigGateway {
|
|
30033
|
+
async initHooks(rootDir, config) {
|
|
30034
|
+
const written = [];
|
|
30035
|
+
const skipped = [];
|
|
30036
|
+
const realRootDir = await realpath(rootDir);
|
|
30037
|
+
const settingsPath = safeJoin(realRootDir, CLAUDE_SETTINGS_PATH);
|
|
30038
|
+
const claudeDir = join(realRootDir, ".claude");
|
|
30039
|
+
// Reject symlinks on .claude/settings.json and all ancestor segments
|
|
30040
|
+
await assertPathHasNoSymbolicLinks(realRootDir, settingsPath);
|
|
30041
|
+
let existing = {};
|
|
30042
|
+
try {
|
|
30043
|
+
const raw = await readFileNoFollow(settingsPath, 1_048_576);
|
|
30044
|
+
const parsed = JSON.parse(raw);
|
|
30045
|
+
if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
30046
|
+
if (hasPrototypePollutionKey(parsed)) {
|
|
30047
|
+
throw new Error("Settings file contains dangerous prototype keys");
|
|
30048
|
+
}
|
|
30049
|
+
existing = parsed;
|
|
30050
|
+
}
|
|
30051
|
+
} catch (error) {
|
|
30052
|
+
if (error instanceof Error && "code" in error) {
|
|
30053
|
+
const code = error.code;
|
|
30054
|
+
if (code === "ENOENT" || code === "ENOTDIR") {
|
|
30055
|
+
existing = {};
|
|
30056
|
+
} else {
|
|
30057
|
+
throw error;
|
|
30058
|
+
}
|
|
30059
|
+
} else if (error instanceof SyntaxError || error instanceof Error && error.message === "Settings file contains dangerous prototype keys") {
|
|
30060
|
+
throw error;
|
|
30061
|
+
} else if (error instanceof Error) {
|
|
30062
|
+
throw error;
|
|
30063
|
+
}
|
|
30064
|
+
}
|
|
30065
|
+
const rawHooks = existing.hooks;
|
|
30066
|
+
const existingHooks = rawHooks !== null && typeof rawHooks === "object" && !Array.isArray(rawHooks) ? rawHooks : {};
|
|
30067
|
+
const existingPreToolUseMatchers = getExistingMatchers(existingHooks, "PreToolUse");
|
|
30068
|
+
const alreadyHasEditHook = existingPreToolUseMatchers.has("Edit") && !config.force;
|
|
30069
|
+
const alreadyHasWriteHook = existingPreToolUseMatchers.has("Write") && !config.force;
|
|
30070
|
+
const alreadyHasStop = Array.isArray(existingHooks.Stop) && !config.force;
|
|
30071
|
+
const alreadyHasSubagentStop = Array.isArray(existingHooks.SubagentStop) && !config.force;
|
|
30072
|
+
const alreadyHasSessionStart = config.addSessionStart && Array.isArray(existingHooks.SessionStart) && !config.force;
|
|
30073
|
+
const allAlreadyPresent = alreadyHasEditHook && alreadyHasWriteHook && alreadyHasStop && alreadyHasSubagentStop && (!config.addSessionStart || alreadyHasSessionStart);
|
|
30074
|
+
if (allAlreadyPresent) {
|
|
30075
|
+
skipped.push(settingsPath);
|
|
30076
|
+
return {
|
|
30077
|
+
written,
|
|
30078
|
+
skipped
|
|
30079
|
+
};
|
|
30080
|
+
}
|
|
30081
|
+
const updatedHooks = {
|
|
30082
|
+
...existingHooks
|
|
30083
|
+
};
|
|
30084
|
+
const missingPreToolUseHooks = PRE_TOOL_USE_HOOKS.filter((h)=>!(h.matcher === "Edit" && alreadyHasEditHook) && !(h.matcher === "Write" && alreadyHasWriteHook));
|
|
30085
|
+
if (missingPreToolUseHooks.length > 0) {
|
|
30086
|
+
// In --force mode, remove any existing Edit/Write matchers before
|
|
30087
|
+
// appending the new ones so we never produce duplicate entries.
|
|
30088
|
+
const existing_ = Array.isArray(existingHooks.PreToolUse) ? config.force ? existingHooks.PreToolUse.filter((e)=>{
|
|
30089
|
+
if (e === null || typeof e !== "object" || Array.isArray(e)) {
|
|
30090
|
+
return true;
|
|
30091
|
+
}
|
|
30092
|
+
const m = e.matcher;
|
|
30093
|
+
return m !== "Edit" && m !== "Write";
|
|
30094
|
+
}) : existingHooks.PreToolUse : [];
|
|
30095
|
+
updatedHooks.PreToolUse = [
|
|
30096
|
+
...existing_,
|
|
30097
|
+
...missingPreToolUseHooks
|
|
30098
|
+
];
|
|
30099
|
+
}
|
|
30100
|
+
// Stop/SubagentStop: written if not already configured with a valid
|
|
30101
|
+
// array. Use --force to replace them.
|
|
30102
|
+
if (!alreadyHasStop) {
|
|
30103
|
+
updatedHooks.Stop = STOP_HOOKS;
|
|
30104
|
+
}
|
|
30105
|
+
if (!alreadyHasSubagentStop) {
|
|
30106
|
+
updatedHooks.SubagentStop = SUBAGENT_STOP_HOOKS;
|
|
30107
|
+
}
|
|
30108
|
+
if (config.addSessionStart && !alreadyHasSessionStart) {
|
|
30109
|
+
updatedHooks.SessionStart = SESSION_START_HOOKS;
|
|
30110
|
+
}
|
|
30111
|
+
const updatedSettings = {
|
|
30112
|
+
...existing,
|
|
30113
|
+
hooks: updatedHooks
|
|
30114
|
+
};
|
|
30115
|
+
const content = `${JSON.stringify(updatedSettings, null, 2)}\n`;
|
|
30116
|
+
await mkdir(claudeDir, {
|
|
30117
|
+
recursive: true
|
|
30118
|
+
});
|
|
30119
|
+
// Re-check after mkdir: a race between the initial check and directory
|
|
30120
|
+
// creation could allow an attacker to replace .claude/ with a symlink.
|
|
30121
|
+
// By the time mkdir returns, the directory exists; if .claude (or any
|
|
30122
|
+
// ancestor) is now a symlink the walk will reach it and throw.
|
|
30123
|
+
await assertPathHasNoSymbolicLinks(realRootDir, settingsPath);
|
|
30124
|
+
// Use a random suffix so the temp path is unpredictable, combined with
|
|
30125
|
+
// O_EXCL so the open fails rather than truncating a pre-existing file.
|
|
30126
|
+
// Together these defeat hardlink pre-creation attacks: an attacker cannot
|
|
30127
|
+
// predict the path to hardlink, and even if they did O_EXCL would reject it.
|
|
30128
|
+
const tmpPath = `${settingsPath}.${randomBytes(8).toString("hex")}.tmp`;
|
|
30129
|
+
// O_NOFOLLOW prevents following a symlink that races between open and write.
|
|
30130
|
+
// O_EXCL guarantees the file is newly created (no truncate of an existing target).
|
|
30131
|
+
const hasNoFollow = typeof constants.O_NOFOLLOW === "number" && constants.O_NOFOLLOW !== 0;
|
|
30132
|
+
const openFlags = constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | (hasNoFollow ? constants.O_NOFOLLOW : 0);
|
|
30133
|
+
let tmpFileHandle;
|
|
30134
|
+
try {
|
|
30135
|
+
tmpFileHandle = await open(tmpPath, openFlags);
|
|
30136
|
+
} catch (error) {
|
|
30137
|
+
if (error instanceof Error && "code" in error) {
|
|
30138
|
+
if (error.code === "ELOOP") {
|
|
30139
|
+
throw new Error(`Symlinks are not allowed for temp path: ${JSON.stringify(tmpPath)}`);
|
|
30140
|
+
}
|
|
30141
|
+
if (error.code === "EEXIST") {
|
|
30142
|
+
// With 8 random bytes (2^64 possibilities) this is astronomically
|
|
30143
|
+
// rare; if it happens it likely indicates a targeted attack.
|
|
30144
|
+
throw new Error(`Temp file already exists (possible collision or attack): ${JSON.stringify(tmpPath)}`);
|
|
30145
|
+
}
|
|
30146
|
+
}
|
|
30147
|
+
throw error;
|
|
30148
|
+
}
|
|
30149
|
+
try {
|
|
30150
|
+
await tmpFileHandle.writeFile(content, "utf8");
|
|
30151
|
+
} finally{
|
|
30152
|
+
await tmpFileHandle.close();
|
|
30153
|
+
}
|
|
30154
|
+
try {
|
|
30155
|
+
await rename(tmpPath, settingsPath);
|
|
30156
|
+
} catch (error) {
|
|
30157
|
+
// Best-effort cleanup: remove the random temp file so it does not
|
|
30158
|
+
// accumulate on repeated failures (e.g. settingsPath unwritable).
|
|
30159
|
+
await unlink(tmpPath).catch(()=>{});
|
|
30160
|
+
throw error;
|
|
30161
|
+
}
|
|
30162
|
+
written.push(settingsPath);
|
|
30163
|
+
return {
|
|
30164
|
+
written,
|
|
30165
|
+
skipped
|
|
30166
|
+
};
|
|
30167
|
+
}
|
|
30168
|
+
}
|
|
30169
|
+
function createInitHooksConfigGateway() {
|
|
30170
|
+
return new InitHooksConfigGateway();
|
|
30171
|
+
}
|
|
30172
|
+
|
|
29993
30173
|
;// CONCATENATED MODULE: ../core/src/gateways/instruction-analysis-gateway.ts
|
|
29994
30174
|
/**
|
|
29995
30175
|
* Gateway for analyzing repository instructions for feedback loop coverage
|
|
@@ -30094,6 +30274,258 @@ function defaultExec(command, args, options) {
|
|
|
30094
30274
|
return new FileSystemInstructionAnalysisGateway();
|
|
30095
30275
|
}
|
|
30096
30276
|
|
|
30277
|
+
// EXTERNAL MODULE: ../../node_modules/yaml/dist/index.js
|
|
30278
|
+
var yaml_dist = __webpack_require__(3519);
|
|
30279
|
+
;// CONCATENATED MODULE: ../core/src/lib/frontmatter.ts
|
|
30280
|
+
/**
|
|
30281
|
+
* Shared YAML frontmatter parser for markdown files.
|
|
30282
|
+
* Extracts YAML data between leading `---` delimiters.
|
|
30283
|
+
*/
|
|
30284
|
+
/**
|
|
30285
|
+
* Parses YAML frontmatter and returns a tagged result:
|
|
30286
|
+
* - `{ ok: true, data }` on success
|
|
30287
|
+
* - `{ ok: false, reason: 'missing' }` when no frontmatter delimiters found
|
|
30288
|
+
* - `{ ok: false, reason: 'invalid', detail }` when YAML is malformed (with error detail)
|
|
30289
|
+
*/ function frontmatter_parseFrontmatterWithError(content) {
|
|
30290
|
+
const lines = content.split("\n");
|
|
30291
|
+
if (lines[0]?.trim() !== "---") {
|
|
30292
|
+
return {
|
|
30293
|
+
ok: false,
|
|
30294
|
+
reason: "missing"
|
|
30295
|
+
};
|
|
30296
|
+
}
|
|
30297
|
+
let endIndex = -1;
|
|
30298
|
+
for(let i = 1; i < lines.length; i++){
|
|
30299
|
+
if (lines[i]?.trim() === "---") {
|
|
30300
|
+
endIndex = i;
|
|
30301
|
+
break;
|
|
30302
|
+
}
|
|
30303
|
+
}
|
|
30304
|
+
if (endIndex === -1) {
|
|
30305
|
+
return {
|
|
30306
|
+
ok: false,
|
|
30307
|
+
reason: "missing"
|
|
30308
|
+
};
|
|
30309
|
+
}
|
|
30310
|
+
const yamlContent = lines.slice(1, endIndex).join("\n");
|
|
30311
|
+
let data;
|
|
30312
|
+
try {
|
|
30313
|
+
const parsed = parseYaml(yamlContent, {
|
|
30314
|
+
maxAliasCount: 0
|
|
30315
|
+
});
|
|
30316
|
+
data = parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
30317
|
+
} catch (error) {
|
|
30318
|
+
const detail = error instanceof Error ? error.message : "Unknown YAML parse error";
|
|
30319
|
+
return {
|
|
30320
|
+
ok: false,
|
|
30321
|
+
reason: "invalid",
|
|
30322
|
+
detail
|
|
30323
|
+
};
|
|
30324
|
+
}
|
|
30325
|
+
const fieldLines = new Map();
|
|
30326
|
+
for(let i = 1; i < endIndex; i++){
|
|
30327
|
+
const match = lines[i]?.match(/^([^\s:][^:]*?):(?:\s|$)/);
|
|
30328
|
+
if (match?.[1]) {
|
|
30329
|
+
fieldLines.set(match[1], i + 1);
|
|
30330
|
+
}
|
|
30331
|
+
}
|
|
30332
|
+
return {
|
|
30333
|
+
ok: true,
|
|
30334
|
+
data: {
|
|
30335
|
+
data: data ?? {},
|
|
30336
|
+
fieldLines,
|
|
30337
|
+
frontmatterStartLine: 1
|
|
30338
|
+
}
|
|
30339
|
+
};
|
|
30340
|
+
}
|
|
30341
|
+
/**
|
|
30342
|
+
* Parses YAML frontmatter from markdown content.
|
|
30343
|
+
*
|
|
30344
|
+
* Returns `null` when the content has no opening `---`, no closing `---`,
|
|
30345
|
+
* or contains invalid YAML.
|
|
30346
|
+
*/ function frontmatter_parseFrontmatter(content) {
|
|
30347
|
+
const result = frontmatter_parseFrontmatterWithError(content);
|
|
30348
|
+
return result.ok ? result.data : null;
|
|
30349
|
+
}
|
|
30350
|
+
|
|
30351
|
+
;// CONCATENATED MODULE: ../core/src/use-cases/lesson-schema.ts
|
|
30352
|
+
|
|
30353
|
+
const SAFE_SLUG = /^[a-z0-9-]+$/;
|
|
30354
|
+
const MAX_TITLE_LENGTH = 200;
|
|
30355
|
+
const MAX_PATTERN_LENGTH = 200;
|
|
30356
|
+
const MAX_PATTERNS = 50;
|
|
30357
|
+
const MAX_TRIGGER_VALUES = 100;
|
|
30358
|
+
const MAX_TRIGGER_VALUE_LENGTH = 200;
|
|
30359
|
+
const lesson_schema_LessonFrontmatterSchema = schemas_object({
|
|
30360
|
+
slug: schemas_string().regex(SAFE_SLUG, "slug must match ^[a-z0-9-]+$"),
|
|
30361
|
+
title: schemas_string().min(1).max(MAX_TITLE_LENGTH),
|
|
30362
|
+
type: schemas_enum([
|
|
30363
|
+
"invariant",
|
|
30364
|
+
"pattern"
|
|
30365
|
+
]),
|
|
30366
|
+
created: schemas_string().regex(/^\d{4}-\d{2}-\d{2}$/, "created must be YYYY-MM-DD"),
|
|
30367
|
+
revised: schemas_string().regex(/^\d{4}-\d{2}-\d{2}$/, "revised must be YYYY-MM-DD"),
|
|
30368
|
+
provenance: schemas_array(schemas_object({
|
|
30369
|
+
pr: schemas_number().int(),
|
|
30370
|
+
// biome-ignore lint/style/useNamingConvention: YAML frontmatter key uses snake_case
|
|
30371
|
+
finding_id: schemas_string(),
|
|
30372
|
+
facet: schemas_string()
|
|
30373
|
+
}).strict()),
|
|
30374
|
+
triggers: schemas_object({
|
|
30375
|
+
paths: schemas_array(schemas_string().min(1).max(MAX_TRIGGER_VALUE_LENGTH)).max(MAX_TRIGGER_VALUES),
|
|
30376
|
+
tags: schemas_array(schemas_string().min(1).max(MAX_TRIGGER_VALUE_LENGTH)).max(MAX_TRIGGER_VALUES),
|
|
30377
|
+
patterns: schemas_array(schemas_string().min(1).max(MAX_PATTERN_LENGTH)).max(MAX_PATTERNS)
|
|
30378
|
+
}).strict()
|
|
30379
|
+
}).strict().refine((data)=>data.revised >= data.created, {
|
|
30380
|
+
message: "revised must be on or after created (lexicographic ISO date compare)",
|
|
30381
|
+
path: [
|
|
30382
|
+
"revised"
|
|
30383
|
+
]
|
|
30384
|
+
});
|
|
30385
|
+
|
|
30386
|
+
;// CONCATENATED MODULE: ../core/src/gateways/lesson-file-gateway.ts
|
|
30387
|
+
/**
|
|
30388
|
+
* Gateway for reading lesson files from .lousy-agents/lessons/.
|
|
30389
|
+
*/
|
|
30390
|
+
|
|
30391
|
+
|
|
30392
|
+
|
|
30393
|
+
|
|
30394
|
+
const MAX_LESSON_FILE_BYTES = 1_048_576; // 1 MB
|
|
30395
|
+
const MAX_LESSON_FILES = 500;
|
|
30396
|
+
const MAX_AGGREGATE_BYTES = (/* unused pure expression or super */ null && (20 * 1024 * 1024)); // 20 MB
|
|
30397
|
+
const LESSONS_RELATIVE_PATH = (0,external_node_path_.join)(".lousy-agents", "lessons");
|
|
30398
|
+
/**
|
|
30399
|
+
* Extracts the markdown body from lesson file content (text after second `---`).
|
|
30400
|
+
*/ function extractBody(content) {
|
|
30401
|
+
const lines = content.split("\n");
|
|
30402
|
+
if (lines[0]?.trim() !== "---") {
|
|
30403
|
+
return content;
|
|
30404
|
+
}
|
|
30405
|
+
let endIndex = -1;
|
|
30406
|
+
for(let i = 1; i < lines.length; i++){
|
|
30407
|
+
if (lines[i]?.trim() === "---") {
|
|
30408
|
+
endIndex = i;
|
|
30409
|
+
break;
|
|
30410
|
+
}
|
|
30411
|
+
}
|
|
30412
|
+
if (endIndex === -1) {
|
|
30413
|
+
return "";
|
|
30414
|
+
}
|
|
30415
|
+
const bodyLines = lines.slice(endIndex + 1);
|
|
30416
|
+
if (bodyLines[0] === "") {
|
|
30417
|
+
return bodyLines.slice(1).join("\n");
|
|
30418
|
+
}
|
|
30419
|
+
return bodyLines.join("\n");
|
|
30420
|
+
}
|
|
30421
|
+
class LessonFileGateway {
|
|
30422
|
+
async readLessons(rootDir) {
|
|
30423
|
+
const realRootDir = await realpath(rootDir);
|
|
30424
|
+
const lessonsDir = join(realRootDir, LESSONS_RELATIVE_PATH);
|
|
30425
|
+
await assertPathHasNoSymbolicLinks(realRootDir, lessonsDir);
|
|
30426
|
+
let dirStat;
|
|
30427
|
+
try {
|
|
30428
|
+
dirStat = await lstat(lessonsDir);
|
|
30429
|
+
} catch (error) {
|
|
30430
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
30431
|
+
return {
|
|
30432
|
+
lessons: [],
|
|
30433
|
+
errors: []
|
|
30434
|
+
};
|
|
30435
|
+
}
|
|
30436
|
+
throw error;
|
|
30437
|
+
}
|
|
30438
|
+
if (!dirStat.isDirectory()) {
|
|
30439
|
+
throw new Error(`Lessons path exists but is not a directory: ${lessonsDir}`);
|
|
30440
|
+
}
|
|
30441
|
+
let entries;
|
|
30442
|
+
try {
|
|
30443
|
+
entries = await readdir(lessonsDir, {
|
|
30444
|
+
withFileTypes: true
|
|
30445
|
+
});
|
|
30446
|
+
} catch (error) {
|
|
30447
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
30448
|
+
const wrapped = new Error(`Cannot read lessons directory ${lessonsDir}: ${reason}`);
|
|
30449
|
+
// Preserve the OS error code so callers can distinguish EACCES
|
|
30450
|
+
// (permission denied) from other failures without parsing the message.
|
|
30451
|
+
if (error instanceof Error && "code" in error) {
|
|
30452
|
+
wrapped.code = error.code;
|
|
30453
|
+
}
|
|
30454
|
+
throw wrapped;
|
|
30455
|
+
}
|
|
30456
|
+
const mdFiles = entries.filter((e)=>e.isFile() && e.name.endsWith(".md")).map((e)=>join(lessonsDir, e.name)).sort();
|
|
30457
|
+
if (mdFiles.length > MAX_LESSON_FILES) {
|
|
30458
|
+
throw new Error(`Lesson file count exceeds limit: ${mdFiles.length} files found (max ${MAX_LESSON_FILES})`);
|
|
30459
|
+
}
|
|
30460
|
+
const lessons = [];
|
|
30461
|
+
const errors = [];
|
|
30462
|
+
let aggregateBytes = 0;
|
|
30463
|
+
for (const filePath of mdFiles){
|
|
30464
|
+
let content;
|
|
30465
|
+
try {
|
|
30466
|
+
content = await readFileNoFollow(filePath, MAX_LESSON_FILE_BYTES);
|
|
30467
|
+
} catch (error) {
|
|
30468
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
30469
|
+
errors.push({
|
|
30470
|
+
filePath,
|
|
30471
|
+
reason
|
|
30472
|
+
});
|
|
30473
|
+
continue;
|
|
30474
|
+
}
|
|
30475
|
+
const byteLength = Buffer.byteLength(content, "utf-8");
|
|
30476
|
+
aggregateBytes += byteLength;
|
|
30477
|
+
if (aggregateBytes > MAX_AGGREGATE_BYTES) {
|
|
30478
|
+
throw new Error(`Aggregate lesson bytes exceed limit: ${aggregateBytes} bytes > ${MAX_AGGREGATE_BYTES} bytes`);
|
|
30479
|
+
}
|
|
30480
|
+
const parseResult = parseFrontmatterWithError(content);
|
|
30481
|
+
if (!parseResult.ok) {
|
|
30482
|
+
const reason = parseResult.reason === "invalid" ? `Invalid YAML frontmatter: ${parseResult.detail}` : "Missing YAML frontmatter";
|
|
30483
|
+
errors.push({
|
|
30484
|
+
filePath,
|
|
30485
|
+
reason
|
|
30486
|
+
});
|
|
30487
|
+
continue;
|
|
30488
|
+
}
|
|
30489
|
+
const schemaResult = LessonFrontmatterSchema.safeParse(parseResult.data.data);
|
|
30490
|
+
if (!schemaResult.success) {
|
|
30491
|
+
const reason = schemaResult.error.issues.map((i)=>`${i.path.join(".")}: ${i.message}`).join("; ");
|
|
30492
|
+
errors.push({
|
|
30493
|
+
filePath,
|
|
30494
|
+
reason
|
|
30495
|
+
});
|
|
30496
|
+
continue;
|
|
30497
|
+
}
|
|
30498
|
+
const fm = schemaResult.data;
|
|
30499
|
+
const body = extractBody(content);
|
|
30500
|
+
const lesson = {
|
|
30501
|
+
slug: fm.slug,
|
|
30502
|
+
title: fm.title,
|
|
30503
|
+
type: fm.type,
|
|
30504
|
+
created: fm.created,
|
|
30505
|
+
revised: fm.revised,
|
|
30506
|
+
provenance: fm.provenance,
|
|
30507
|
+
triggers: {
|
|
30508
|
+
paths: fm.triggers.paths,
|
|
30509
|
+
tags: fm.triggers.tags,
|
|
30510
|
+
patterns: fm.triggers.patterns
|
|
30511
|
+
},
|
|
30512
|
+
body
|
|
30513
|
+
};
|
|
30514
|
+
lessons.push({
|
|
30515
|
+
lesson,
|
|
30516
|
+
filePath
|
|
30517
|
+
});
|
|
30518
|
+
}
|
|
30519
|
+
return {
|
|
30520
|
+
lessons,
|
|
30521
|
+
errors
|
|
30522
|
+
};
|
|
30523
|
+
}
|
|
30524
|
+
}
|
|
30525
|
+
function createLessonFileGateway() {
|
|
30526
|
+
return new LessonFileGateway();
|
|
30527
|
+
}
|
|
30528
|
+
|
|
30097
30529
|
;// CONCATENATED MODULE: ../../node_modules/consola/dist/core.mjs
|
|
30098
30530
|
const LogLevels = {
|
|
30099
30531
|
silent: Number.NEGATIVE_INFINITY,
|
|
@@ -31902,58 +32334,6 @@ const PackageJsonSchema = schemas_object({
|
|
|
31902
32334
|
return new FileSystemSkillFileGateway();
|
|
31903
32335
|
}
|
|
31904
32336
|
|
|
31905
|
-
// EXTERNAL MODULE: ../../node_modules/yaml/dist/index.js
|
|
31906
|
-
var yaml_dist = __webpack_require__(3519);
|
|
31907
|
-
;// CONCATENATED MODULE: ../core/src/lib/frontmatter.ts
|
|
31908
|
-
/**
|
|
31909
|
-
* Shared YAML frontmatter parser for markdown files.
|
|
31910
|
-
* Extracts YAML data between leading `---` delimiters.
|
|
31911
|
-
*/
|
|
31912
|
-
/**
|
|
31913
|
-
* Parses YAML frontmatter from markdown content.
|
|
31914
|
-
*
|
|
31915
|
-
* Returns `null` when the content has no opening `---`, no closing `---`,
|
|
31916
|
-
* or contains invalid YAML.
|
|
31917
|
-
*/ function frontmatter_parseFrontmatter(content) {
|
|
31918
|
-
const lines = content.split("\n");
|
|
31919
|
-
if (lines[0]?.trim() !== "---") {
|
|
31920
|
-
return null;
|
|
31921
|
-
}
|
|
31922
|
-
let endIndex = -1;
|
|
31923
|
-
for(let i = 1; i < lines.length; i++){
|
|
31924
|
-
if (lines[i]?.trim() === "---") {
|
|
31925
|
-
endIndex = i;
|
|
31926
|
-
break;
|
|
31927
|
-
}
|
|
31928
|
-
}
|
|
31929
|
-
if (endIndex === -1) {
|
|
31930
|
-
return null;
|
|
31931
|
-
}
|
|
31932
|
-
const yamlContent = lines.slice(1, endIndex).join("\n");
|
|
31933
|
-
let data;
|
|
31934
|
-
try {
|
|
31935
|
-
const parsed = parseYaml(yamlContent, {
|
|
31936
|
-
maxAliasCount: 0
|
|
31937
|
-
});
|
|
31938
|
-
data = parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
31939
|
-
} catch {
|
|
31940
|
-
return null;
|
|
31941
|
-
}
|
|
31942
|
-
const fieldLines = new Map();
|
|
31943
|
-
for(let i = 1; i < endIndex; i++){
|
|
31944
|
-
// Match YAML top-level field names: non-whitespace start, any chars except colon, then colon followed by whitespace or end-of-line
|
|
31945
|
-
const match = lines[i]?.match(/^([^\s:][^:]*?):(?:\s|$)/);
|
|
31946
|
-
if (match?.[1]) {
|
|
31947
|
-
fieldLines.set(match[1], i + 1);
|
|
31948
|
-
}
|
|
31949
|
-
}
|
|
31950
|
-
return {
|
|
31951
|
-
data: data ?? {},
|
|
31952
|
-
fieldLines,
|
|
31953
|
-
frontmatterStartLine: 1
|
|
31954
|
-
};
|
|
31955
|
-
}
|
|
31956
|
-
|
|
31957
32337
|
;// CONCATENATED MODULE: ../core/src/gateways/skill-lint-gateway.ts
|
|
31958
32338
|
/**
|
|
31959
32339
|
* Gateway for skill lint file system operations.
|
|
@@ -32483,6 +32863,8 @@ function createWorkflowGateway(cwd) {
|
|
|
32483
32863
|
|
|
32484
32864
|
|
|
32485
32865
|
|
|
32866
|
+
|
|
32867
|
+
|
|
32486
32868
|
;// CONCATENATED MODULE: ./src/tools/types.ts
|
|
32487
32869
|
/**
|
|
32488
32870
|
* Shared types and utilities for MCP tool handlers.
|
|
@@ -48922,7 +49304,7 @@ function default_ok() {}
|
|
|
48922
49304
|
|
|
48923
49305
|
function unreachable() {}
|
|
48924
49306
|
|
|
48925
|
-
;// CONCATENATED MODULE: ../../node_modules/
|
|
49307
|
+
;// CONCATENATED MODULE: ../../node_modules/is-plain-obj/index.js
|
|
48926
49308
|
function is_plain_obj_isPlainObject(value) {
|
|
48927
49309
|
if (typeof value !== 'object' || value === null) {
|
|
48928
49310
|
return false;
|
|
@@ -51684,7 +52066,7 @@ const HEADING_PATTERN_DESCRIPTIONS = new Map(Object.entries(HEADING_PATTERN_DESC
|
|
|
51684
52066
|
|
|
51685
52067
|
/** Maximum number of raw heading pattern entries accepted before deduplication. */ const MAX_RAW_HEADING_PATTERNS = 1000;
|
|
51686
52068
|
/** Maximum number of heading patterns accepted in a single execute() call. */ const MAX_HEADING_PATTERNS = 50;
|
|
51687
|
-
/** Maximum character length for a single heading pattern. */ const
|
|
52069
|
+
/** Maximum character length for a single heading pattern. */ const analyze_instruction_quality_MAX_PATTERN_LENGTH = 200;
|
|
51688
52070
|
/**
|
|
51689
52071
|
* Lowercase-keyed lookup built once from HEADING_PATTERN_DESCRIPTIONS.
|
|
51690
52072
|
* Enables description lookup regardless of the casing callers supply for patterns.
|
|
@@ -51696,7 +52078,7 @@ const HEADING_PATTERN_DESCRIPTIONS = new Map(Object.entries(HEADING_PATTERN_DESC
|
|
|
51696
52078
|
* Input for the analyze instruction quality use case.
|
|
51697
52079
|
*/ const AnalyzeInstructionQualityInputSchema = schemas_object({
|
|
51698
52080
|
targetDir: schemas_string().min(1, "Target directory is required"),
|
|
51699
|
-
headingPatterns: schemas_array(schemas_string().max(
|
|
52081
|
+
headingPatterns: schemas_array(schemas_string().max(analyze_instruction_quality_MAX_PATTERN_LENGTH * 2)).max(MAX_RAW_HEADING_PATTERNS).optional(),
|
|
51700
52082
|
proximityWindow: schemas_number().int().positive().optional()
|
|
51701
52083
|
});
|
|
51702
52084
|
/**
|
|
@@ -51796,8 +52178,8 @@ const HEADING_PATTERN_DESCRIPTIONS = new Map(Object.entries(HEADING_PATTERN_DESC
|
|
|
51796
52178
|
if (trimmed.length === 0) {
|
|
51797
52179
|
throw new Error("headingPatterns must not contain empty or whitespace-only entries");
|
|
51798
52180
|
}
|
|
51799
|
-
if (trimmed.length >
|
|
51800
|
-
throw new Error(`headingPatterns entries must not exceed ${
|
|
52181
|
+
if (trimmed.length > analyze_instruction_quality_MAX_PATTERN_LENGTH) {
|
|
52182
|
+
throw new Error(`headingPatterns entries must not exceed ${analyze_instruction_quality_MAX_PATTERN_LENGTH} characters`);
|
|
51801
52183
|
}
|
|
51802
52184
|
const lower = trimmed.toLowerCase();
|
|
51803
52185
|
if (!seenLower.has(lower)) {
|
|
@@ -63814,4 +64196,4 @@ if (installedChunkData !== 0) { // 0 means "already installed".'
|
|
|
63814
64196
|
// module factories are used so entry inlining is disabled
|
|
63815
64197
|
// startup
|
|
63816
64198
|
// Load entry module and return exports
|
|
63817
|
-
var __webpack_exports__ = __webpack_require__(
|
|
64199
|
+
var __webpack_exports__ = __webpack_require__(8050);
|