@lousy-agents/mcp 5.18.1 → 5.18.2
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/mcp-server.js +140 -121
- package/package.json +3 -2
package/dist/mcp-server.js
CHANGED
|
@@ -34967,8 +34967,9 @@ async function readVersionFileContent(targetDir, relativePath) {
|
|
|
34967
34967
|
continue;
|
|
34968
34968
|
}
|
|
34969
34969
|
if (await file_system_utils_pathExistsWithinRoot(targetDir, pmConfig.manifestFile)) {
|
|
34970
|
-
const
|
|
34971
|
-
const
|
|
34970
|
+
const { lockfile } = pmConfig;
|
|
34971
|
+
const lockfilePath = lockfile ? await file_system_utils_resolveSafePath(targetDir, lockfile) : undefined;
|
|
34972
|
+
const hasLockfile = lockfilePath && lockfile ? await file_system_utils_pathExistsWithinRoot(targetDir, lockfile) : false;
|
|
34972
34973
|
if (pmConfig.requiresLockfile && !hasLockfile) {
|
|
34973
34974
|
continue;
|
|
34974
34975
|
}
|
|
@@ -34985,8 +34986,9 @@ async function readVersionFileContent(targetDir, relativePath) {
|
|
|
34985
34986
|
const packageManagers = [];
|
|
34986
34987
|
for (const pmConfig of otherPackageManagers){
|
|
34987
34988
|
if (await file_system_utils_pathExistsWithinRoot(targetDir, pmConfig.manifestFile)) {
|
|
34988
|
-
const
|
|
34989
|
-
const
|
|
34989
|
+
const { lockfile } = pmConfig;
|
|
34990
|
+
const lockfilePath = lockfile ? await file_system_utils_resolveSafePath(targetDir, lockfile) : undefined;
|
|
34991
|
+
const hasLockfile = lockfilePath && lockfile ? await file_system_utils_pathExistsWithinRoot(targetDir, lockfile) : false;
|
|
34990
34992
|
if (pmConfig.requiresLockfile && !hasLockfile) {
|
|
34991
34993
|
continue;
|
|
34992
34994
|
}
|
|
@@ -35148,11 +35150,18 @@ function defaultExec(command, args, options) {
|
|
|
35148
35150
|
throw new Error("Not authenticated");
|
|
35149
35151
|
}
|
|
35150
35152
|
try {
|
|
35151
|
-
|
|
35153
|
+
const params = {
|
|
35152
35154
|
owner,
|
|
35153
35155
|
repo,
|
|
35154
|
-
|
|
35155
|
-
|
|
35156
|
+
name: payload.name,
|
|
35157
|
+
enforcement: payload.enforcement,
|
|
35158
|
+
target: payload.target,
|
|
35159
|
+
// biome-ignore lint/style/useNamingConvention: GitHub API schema requires snake_case
|
|
35160
|
+
bypass_actors: payload.bypass_actors,
|
|
35161
|
+
conditions: payload.conditions,
|
|
35162
|
+
rules: payload.rules
|
|
35163
|
+
};
|
|
35164
|
+
await this.octokit.rest.repos.createRepoRuleset(params);
|
|
35156
35165
|
} catch (error) {
|
|
35157
35166
|
const details = formatOctokitError(error);
|
|
35158
35167
|
throw new Error(`Failed to create ruleset for ${owner}/${repo}: ${details}`);
|
|
@@ -57474,120 +57483,6 @@ function lib_isUint8Array(value) {
|
|
|
57474
57483
|
*/
|
|
57475
57484
|
const remark = unified().use(remarkParse).use(remarkStringify).freeze()
|
|
57476
57485
|
|
|
57477
|
-
;// CONCATENATED MODULE: ../core/src/gateways/markdown-ast-gateway.ts
|
|
57478
|
-
/**
|
|
57479
|
-
* Gateway for parsing Markdown files into AST using remark.
|
|
57480
|
-
* Extracts structural features like headings, code blocks, and paragraphs.
|
|
57481
|
-
*/
|
|
57482
|
-
|
|
57483
|
-
|
|
57484
|
-
/** Maximum instruction file size: 1 MB */ const markdown_ast_gateway_MAX_INSTRUCTION_FILE_BYTES = 1_048_576;
|
|
57485
|
-
/**
|
|
57486
|
-
* Remark-based implementation of the Markdown AST gateway.
|
|
57487
|
-
*/ class RemarkMarkdownAstGateway {
|
|
57488
|
-
async parseFile(filePath) {
|
|
57489
|
-
const content = await read_file_no_follow_readFileNoFollow(filePath, markdown_ast_gateway_MAX_INSTRUCTION_FILE_BYTES);
|
|
57490
|
-
return this.parseContent(content);
|
|
57491
|
-
}
|
|
57492
|
-
parseContent(content) {
|
|
57493
|
-
const processor = remark();
|
|
57494
|
-
const ast = processor.parse(content);
|
|
57495
|
-
const headings = [];
|
|
57496
|
-
const codeBlocks = [];
|
|
57497
|
-
const inlineCodes = [];
|
|
57498
|
-
lib_visit(ast, "heading", (node)=>{
|
|
57499
|
-
const text = this.extractHeadingText(node);
|
|
57500
|
-
headings.push({
|
|
57501
|
-
text,
|
|
57502
|
-
depth: node.depth,
|
|
57503
|
-
position: {
|
|
57504
|
-
line: node.position?.start.line ?? 0
|
|
57505
|
-
}
|
|
57506
|
-
});
|
|
57507
|
-
});
|
|
57508
|
-
// Track code blocks with their node index in root children
|
|
57509
|
-
for(let i = 0; i < ast.children.length; i++){
|
|
57510
|
-
const child = ast.children[i];
|
|
57511
|
-
if (child.type === "code") {
|
|
57512
|
-
const codeNode = child;
|
|
57513
|
-
codeBlocks.push({
|
|
57514
|
-
value: codeNode.value,
|
|
57515
|
-
lang: codeNode.lang ?? undefined,
|
|
57516
|
-
position: {
|
|
57517
|
-
line: codeNode.position?.start.line ?? 0
|
|
57518
|
-
},
|
|
57519
|
-
nodeIndex: i
|
|
57520
|
-
});
|
|
57521
|
-
}
|
|
57522
|
-
}
|
|
57523
|
-
lib_visit(ast, "inlineCode", (node)=>{
|
|
57524
|
-
inlineCodes.push({
|
|
57525
|
-
value: node.value,
|
|
57526
|
-
position: {
|
|
57527
|
-
line: node.position?.start.line ?? 0
|
|
57528
|
-
}
|
|
57529
|
-
});
|
|
57530
|
-
});
|
|
57531
|
-
return {
|
|
57532
|
-
headings,
|
|
57533
|
-
codeBlocks,
|
|
57534
|
-
inlineCodes,
|
|
57535
|
-
ast
|
|
57536
|
-
};
|
|
57537
|
-
}
|
|
57538
|
-
findConditionalKeywordsInProximity(structure, codeBlockNodeIndex, proximityWindow, keywords) {
|
|
57539
|
-
const ast = structure.ast;
|
|
57540
|
-
const endIndex = Math.min(ast.children.length, codeBlockNodeIndex + 1 + proximityWindow);
|
|
57541
|
-
for(let i = codeBlockNodeIndex + 1; i < endIndex; i++){
|
|
57542
|
-
const sibling = ast.children[i];
|
|
57543
|
-
const text = extractTextFromNode(sibling);
|
|
57544
|
-
const lowerText = text.toLowerCase();
|
|
57545
|
-
for (const keyword of keywords){
|
|
57546
|
-
if (containsWordBoundary(lowerText, keyword.toLowerCase())) {
|
|
57547
|
-
return true;
|
|
57548
|
-
}
|
|
57549
|
-
}
|
|
57550
|
-
}
|
|
57551
|
-
return false;
|
|
57552
|
-
}
|
|
57553
|
-
extractHeadingText(node) {
|
|
57554
|
-
const parts = [];
|
|
57555
|
-
lib_visit(node, "text", (textNode)=>{
|
|
57556
|
-
parts.push(textNode.value);
|
|
57557
|
-
});
|
|
57558
|
-
return parts.join("");
|
|
57559
|
-
}
|
|
57560
|
-
}
|
|
57561
|
-
/**
|
|
57562
|
-
* Checks if text contains a keyword at a word boundary (safe string matching, no regex).
|
|
57563
|
-
*/ function containsWordBoundary(text, keyword) {
|
|
57564
|
-
const index = text.indexOf(keyword);
|
|
57565
|
-
if (index === -1) {
|
|
57566
|
-
return false;
|
|
57567
|
-
}
|
|
57568
|
-
const charBefore = index > 0 ? text[index - 1] : " ";
|
|
57569
|
-
const charAfter = index + keyword.length < text.length ? text[index + keyword.length] : " ";
|
|
57570
|
-
const isWordBoundaryBefore = !/[a-z0-9]/i.test(charBefore);
|
|
57571
|
-
const isWordBoundaryAfter = !/[a-z0-9]/i.test(charAfter);
|
|
57572
|
-
return isWordBoundaryBefore && isWordBoundaryAfter;
|
|
57573
|
-
}
|
|
57574
|
-
/**
|
|
57575
|
-
* Extracts plain text content from any AST node recursively.
|
|
57576
|
-
*/ function extractTextFromNode(node) {
|
|
57577
|
-
if (node.value && typeof node.value === "string") {
|
|
57578
|
-
return node.value;
|
|
57579
|
-
}
|
|
57580
|
-
if (Array.isArray(node.children)) {
|
|
57581
|
-
return node.children.map((child)=>extractTextFromNode(child)).join(" ");
|
|
57582
|
-
}
|
|
57583
|
-
return "";
|
|
57584
|
-
}
|
|
57585
|
-
/**
|
|
57586
|
-
* Creates and returns the default Markdown AST gateway.
|
|
57587
|
-
*/ function createMarkdownAstGateway() {
|
|
57588
|
-
return new RemarkMarkdownAstGateway();
|
|
57589
|
-
}
|
|
57590
|
-
|
|
57591
57486
|
;// CONCATENATED MODULE: ../core/src/entities/instruction-quality.ts
|
|
57592
57487
|
/**
|
|
57593
57488
|
* Core domain entities for instruction quality analysis.
|
|
@@ -57639,6 +57534,9 @@ const HEADING_PATTERN_DESCRIPTIONS = new Map(Object.entries(HEADING_PATTERN_DESC
|
|
|
57639
57534
|
* Orchestrates discovery, AST parsing, and scoring of feedback loop documentation.
|
|
57640
57535
|
*/
|
|
57641
57536
|
|
|
57537
|
+
/** Type guard narrowing an `unknown` AST child to {@link AstNodeLike}. */ function isAstNodeLike(node) {
|
|
57538
|
+
return typeof node === "object" && node !== null && "type" in node && typeof node.type === "string";
|
|
57539
|
+
}
|
|
57642
57540
|
/** Maximum number of raw heading pattern entries accepted before deduplication. */ const MAX_RAW_HEADING_PATTERNS = 1000;
|
|
57643
57541
|
/** Maximum number of heading patterns accepted in a single execute() call. */ const MAX_HEADING_PATTERNS = 50;
|
|
57644
57542
|
/** Maximum character length for a single heading pattern. */ const analyze_instruction_quality_MAX_PATTERN_LENGTH = 200;
|
|
@@ -57994,6 +57892,9 @@ const HEADING_PATTERN_DESCRIPTIONS = new Map(Object.entries(HEADING_PATTERN_DESC
|
|
|
57994
57892
|
return parts.join(" ");
|
|
57995
57893
|
}
|
|
57996
57894
|
collectText(node, parts) {
|
|
57895
|
+
if (!isAstNodeLike(node)) {
|
|
57896
|
+
return;
|
|
57897
|
+
}
|
|
57997
57898
|
if (node.type === "text" && typeof node.value === "string") {
|
|
57998
57899
|
parts.push(node.value);
|
|
57999
57900
|
}
|
|
@@ -58140,6 +58041,124 @@ const HEADING_PATTERN_DESCRIPTIONS = new Map(Object.entries(HEADING_PATTERN_DESC
|
|
|
58140
58041
|
}
|
|
58141
58042
|
}
|
|
58142
58043
|
|
|
58044
|
+
;// CONCATENATED MODULE: ../core/src/gateways/markdown-ast-gateway.ts
|
|
58045
|
+
/**
|
|
58046
|
+
* Gateway for parsing Markdown files into AST using remark.
|
|
58047
|
+
* Extracts structural features like headings, code blocks, and paragraphs.
|
|
58048
|
+
*/
|
|
58049
|
+
|
|
58050
|
+
|
|
58051
|
+
|
|
58052
|
+
/** Maximum instruction file size: 1 MB */ const markdown_ast_gateway_MAX_INSTRUCTION_FILE_BYTES = 1_048_576;
|
|
58053
|
+
/**
|
|
58054
|
+
* Remark-based implementation of the Markdown AST gateway.
|
|
58055
|
+
*/ class RemarkMarkdownAstGateway {
|
|
58056
|
+
async parseFile(filePath) {
|
|
58057
|
+
const content = await read_file_no_follow_readFileNoFollow(filePath, markdown_ast_gateway_MAX_INSTRUCTION_FILE_BYTES);
|
|
58058
|
+
return this.parseContent(content);
|
|
58059
|
+
}
|
|
58060
|
+
parseContent(content) {
|
|
58061
|
+
const processor = remark();
|
|
58062
|
+
const ast = processor.parse(content);
|
|
58063
|
+
const headings = [];
|
|
58064
|
+
const codeBlocks = [];
|
|
58065
|
+
const inlineCodes = [];
|
|
58066
|
+
lib_visit(ast, "heading", (node)=>{
|
|
58067
|
+
const text = this.extractHeadingText(node);
|
|
58068
|
+
headings.push({
|
|
58069
|
+
text,
|
|
58070
|
+
depth: node.depth,
|
|
58071
|
+
position: {
|
|
58072
|
+
line: node.position?.start.line ?? 0
|
|
58073
|
+
}
|
|
58074
|
+
});
|
|
58075
|
+
});
|
|
58076
|
+
// Track code blocks with their node index in root children
|
|
58077
|
+
for(let i = 0; i < ast.children.length; i++){
|
|
58078
|
+
const child = ast.children[i];
|
|
58079
|
+
if (child.type === "code") {
|
|
58080
|
+
const codeNode = child;
|
|
58081
|
+
codeBlocks.push({
|
|
58082
|
+
value: codeNode.value,
|
|
58083
|
+
lang: codeNode.lang ?? undefined,
|
|
58084
|
+
position: {
|
|
58085
|
+
line: codeNode.position?.start.line ?? 0
|
|
58086
|
+
},
|
|
58087
|
+
nodeIndex: i
|
|
58088
|
+
});
|
|
58089
|
+
}
|
|
58090
|
+
}
|
|
58091
|
+
lib_visit(ast, "inlineCode", (node)=>{
|
|
58092
|
+
inlineCodes.push({
|
|
58093
|
+
value: node.value,
|
|
58094
|
+
position: {
|
|
58095
|
+
line: node.position?.start.line ?? 0
|
|
58096
|
+
}
|
|
58097
|
+
});
|
|
58098
|
+
});
|
|
58099
|
+
return {
|
|
58100
|
+
headings,
|
|
58101
|
+
codeBlocks,
|
|
58102
|
+
inlineCodes,
|
|
58103
|
+
ast
|
|
58104
|
+
};
|
|
58105
|
+
}
|
|
58106
|
+
findConditionalKeywordsInProximity(structure, codeBlockNodeIndex, proximityWindow, keywords) {
|
|
58107
|
+
const ast = structure.ast;
|
|
58108
|
+
const endIndex = Math.min(ast.children.length, codeBlockNodeIndex + 1 + proximityWindow);
|
|
58109
|
+
for(let i = codeBlockNodeIndex + 1; i < endIndex; i++){
|
|
58110
|
+
const sibling = ast.children[i];
|
|
58111
|
+
const text = extractTextFromNode(sibling);
|
|
58112
|
+
const lowerText = text.toLowerCase();
|
|
58113
|
+
for (const keyword of keywords){
|
|
58114
|
+
if (containsWordBoundary(lowerText, keyword.toLowerCase())) {
|
|
58115
|
+
return true;
|
|
58116
|
+
}
|
|
58117
|
+
}
|
|
58118
|
+
}
|
|
58119
|
+
return false;
|
|
58120
|
+
}
|
|
58121
|
+
extractHeadingText(node) {
|
|
58122
|
+
const parts = [];
|
|
58123
|
+
lib_visit(node, "text", (textNode)=>{
|
|
58124
|
+
parts.push(textNode.value);
|
|
58125
|
+
});
|
|
58126
|
+
return parts.join("");
|
|
58127
|
+
}
|
|
58128
|
+
}
|
|
58129
|
+
/**
|
|
58130
|
+
* Checks if text contains a keyword at a word boundary (safe string matching, no regex).
|
|
58131
|
+
*/ function containsWordBoundary(text, keyword) {
|
|
58132
|
+
const index = text.indexOf(keyword);
|
|
58133
|
+
if (index === -1) {
|
|
58134
|
+
return false;
|
|
58135
|
+
}
|
|
58136
|
+
const charBefore = index > 0 ? text[index - 1] : " ";
|
|
58137
|
+
const charAfter = index + keyword.length < text.length ? text[index + keyword.length] : " ";
|
|
58138
|
+
const isWordBoundaryBefore = !/[a-z0-9]/i.test(charBefore);
|
|
58139
|
+
const isWordBoundaryAfter = !/[a-z0-9]/i.test(charAfter);
|
|
58140
|
+
return isWordBoundaryBefore && isWordBoundaryAfter;
|
|
58141
|
+
}
|
|
58142
|
+
/**
|
|
58143
|
+
* Extracts plain text content from any AST node recursively.
|
|
58144
|
+
*/ function extractTextFromNode(node) {
|
|
58145
|
+
if (!isAstNodeLike(node)) {
|
|
58146
|
+
return "";
|
|
58147
|
+
}
|
|
58148
|
+
if (node.value && typeof node.value === "string") {
|
|
58149
|
+
return node.value;
|
|
58150
|
+
}
|
|
58151
|
+
if (Array.isArray(node.children)) {
|
|
58152
|
+
return node.children.map((child)=>extractTextFromNode(child)).join(" ");
|
|
58153
|
+
}
|
|
58154
|
+
return "";
|
|
58155
|
+
}
|
|
58156
|
+
/**
|
|
58157
|
+
* Creates and returns the default Markdown AST gateway.
|
|
58158
|
+
*/ function createMarkdownAstGateway() {
|
|
58159
|
+
return new RemarkMarkdownAstGateway();
|
|
58160
|
+
}
|
|
58161
|
+
|
|
58143
58162
|
;// CONCATENATED MODULE: ./src/tools/analyze-instruction-quality.ts
|
|
58144
58163
|
/**
|
|
58145
58164
|
* MCP tool handler for analyzing instruction quality.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lousy-agents/mcp",
|
|
3
|
-
"version": "5.18.
|
|
3
|
+
"version": "5.18.2",
|
|
4
4
|
"description": "MCP server for lousy-agents - provides AI coding assistant tools via the Model Context Protocol",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -33,7 +33,8 @@
|
|
|
33
33
|
"lousy-agents-mcp": "dist/mcp-server.js"
|
|
34
34
|
},
|
|
35
35
|
"scripts": {
|
|
36
|
-
"build": "rspack build --config rspack.config.ts && chmod +x dist/mcp-server.js"
|
|
36
|
+
"build": "rspack build --config rspack.config.ts && chmod +x dist/mcp-server.js",
|
|
37
|
+
"typecheck": "tsc --noEmit"
|
|
37
38
|
},
|
|
38
39
|
"dependencies": {
|
|
39
40
|
"@modelcontextprotocol/sdk": "1.30.0",
|