@lousy-agents/mcp 5.12.2 → 5.13.1

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.
Files changed (2) hide show
  1. package/dist/mcp-server.js +148 -144
  2. package/package.json +2 -2
@@ -6559,7 +6559,7 @@ function escapeJsonPtr(str) {
6559
6559
 
6560
6560
 
6561
6561
  },
6562
- 5714(__unused_rspack_module, __unused_rspack___webpack_exports__, __webpack_require__) {
6562
+ 832(__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);
@@ -8374,7 +8374,7 @@ const safeDecodeAsync = /* @__PURE__*/ _safeDecodeAsync($ZodRealError);
8374
8374
  const versions_version = {
8375
8375
  major: 4,
8376
8376
  minor: 4,
8377
- patch: 2,
8377
+ patch: 3,
8378
8378
  };
8379
8379
 
8380
8380
  ;// CONCATENATED MODULE: ../../node_modules/zod/v4/core/schemas.js
@@ -10097,6 +10097,7 @@ const $ZodFile = /*@__PURE__*/ (/* unused pure expression or super */ null && (c
10097
10097
  })));
10098
10098
  const $ZodTransform = /*@__PURE__*/ $constructor("$ZodTransform", (inst, def) => {
10099
10099
  $ZodType.init(inst, def);
10100
+ inst._zod.optin = "optional";
10100
10101
  inst._zod.parse = (payload, ctx) => {
10101
10102
  if (ctx.direction === "backward") {
10102
10103
  throw new $ZodEncodeError(inst.constructor.name);
@@ -10106,6 +10107,7 @@ const $ZodTransform = /*@__PURE__*/ $constructor("$ZodTransform", (inst, def) =>
10106
10107
  const output = _out instanceof Promise ? _out : Promise.resolve(_out);
10107
10108
  return output.then((output) => {
10108
10109
  payload.value = output;
10110
+ payload.fallback = true;
10109
10111
  return payload;
10110
10112
  });
10111
10113
  }
@@ -10113,11 +10115,12 @@ const $ZodTransform = /*@__PURE__*/ $constructor("$ZodTransform", (inst, def) =>
10113
10115
  throw new $ZodAsyncError();
10114
10116
  }
10115
10117
  payload.value = _out;
10118
+ payload.fallback = true;
10116
10119
  return payload;
10117
10120
  };
10118
10121
  });
10119
10122
  function handleOptionalResult(result, input) {
10120
- if (result.issues.length && input === undefined) {
10123
+ if (input === undefined && (result.issues.length || result.fallback)) {
10121
10124
  return { issues: [], value: undefined };
10122
10125
  }
10123
10126
  return result;
@@ -10135,10 +10138,11 @@ const $ZodOptional = /*@__PURE__*/ $constructor("$ZodOptional", (inst, def) => {
10135
10138
  });
10136
10139
  inst._zod.parse = (payload, ctx) => {
10137
10140
  if (def.innerType._zod.optin === "optional") {
10141
+ const input = payload.value;
10138
10142
  const result = def.innerType._zod.run(payload, ctx);
10139
10143
  if (result instanceof Promise)
10140
- return result.then((r) => handleOptionalResult(r, payload.value));
10141
- return handleOptionalResult(result, payload.value);
10144
+ return result.then((r) => handleOptionalResult(r, input));
10145
+ return handleOptionalResult(result, input);
10142
10146
  }
10143
10147
  if (payload.value === undefined) {
10144
10148
  return payload;
@@ -10265,7 +10269,7 @@ const $ZodSuccess = /*@__PURE__*/ (/* unused pure expression or super */ null &&
10265
10269
  })));
10266
10270
  const $ZodCatch = /*@__PURE__*/ $constructor("$ZodCatch", (inst, def) => {
10267
10271
  $ZodType.init(inst, def);
10268
- defineLazy(inst._zod, "optin", () => def.innerType._zod.optin);
10272
+ inst._zod.optin = "optional";
10269
10273
  defineLazy(inst._zod, "optout", () => def.innerType._zod.optout);
10270
10274
  defineLazy(inst._zod, "values", () => def.innerType._zod.values);
10271
10275
  inst._zod.parse = (payload, ctx) => {
@@ -10286,6 +10290,7 @@ const $ZodCatch = /*@__PURE__*/ $constructor("$ZodCatch", (inst, def) => {
10286
10290
  input: payload.value,
10287
10291
  });
10288
10292
  payload.issues = [];
10293
+ payload.fallback = true;
10289
10294
  }
10290
10295
  return payload;
10291
10296
  });
@@ -10300,6 +10305,7 @@ const $ZodCatch = /*@__PURE__*/ $constructor("$ZodCatch", (inst, def) => {
10300
10305
  input: payload.value,
10301
10306
  });
10302
10307
  payload.issues = [];
10308
+ payload.fallback = true;
10303
10309
  }
10304
10310
  return payload;
10305
10311
  };
@@ -10346,7 +10352,7 @@ function handlePipeResult(left, next, ctx) {
10346
10352
  left.aborted = true;
10347
10353
  return left;
10348
10354
  }
10349
- return next._zod.run({ value: left.value, issues: left.issues }, ctx);
10355
+ return next._zod.run({ value: left.value, issues: left.issues, fallback: left.fallback }, ctx);
10350
10356
  }
10351
10357
  const $ZodCodec = /*@__PURE__*/ (/* unused pure expression or super */ null && (core.$constructor("$ZodCodec", (inst, def) => {
10352
10358
  $ZodType.init(inst, def);
@@ -10404,8 +10410,6 @@ function handleCodecTxResult(left, value, nextSchema, ctx) {
10404
10410
  }
10405
10411
  const $ZodPreprocess = /*@__PURE__*/ $constructor("$ZodPreprocess", (inst, def) => {
10406
10412
  $ZodPipe.init(inst, def);
10407
- defineLazy(inst._zod, "optin", () => def.out._zod.optin);
10408
- defineLazy(inst._zod, "optout", () => def.out._zod.optout);
10409
10413
  });
10410
10414
  const $ZodReadonly = /*@__PURE__*/ $constructor("$ZodReadonly", (inst, def) => {
10411
10415
  $ZodType.init(inst, def);
@@ -13992,10 +13996,12 @@ const ZodTransform = /*@__PURE__*/ $constructor("ZodTransform", (inst, def) => {
13992
13996
  if (output instanceof Promise) {
13993
13997
  return output.then((output) => {
13994
13998
  payload.value = output;
13999
+ payload.fallback = true;
13995
14000
  return payload;
13996
14001
  });
13997
14002
  }
13998
14003
  payload.value = output;
14004
+ payload.fallback = true;
13999
14005
  return payload;
14000
14006
  };
14001
14007
  });
@@ -29484,6 +29490,26 @@ var compat_ZodFirstPartyTypeKind;
29484
29490
  setupActionPatterns: DEFAULT_SETUP_ACTION_PATTERNS,
29485
29491
  packageManagers: DEFAULT_PACKAGE_MANAGERS
29486
29492
  };
29493
+ /**
29494
+ * Gets a version type to action name mapping from config.
29495
+ * Returns a partial record as not all types may be configured.
29496
+ */ function getVersionTypeToActionMap(config) {
29497
+ const map = {};
29498
+ for (const action of config.setupActions){
29499
+ map[action.type] = action.action;
29500
+ }
29501
+ return map;
29502
+ }
29503
+ /**
29504
+ * Gets a version file type to config key mapping from config.
29505
+ * Returns a partial record as not all types may be configured.
29506
+ */ function getVersionFileConfigKeyMap(config) {
29507
+ const map = {};
29508
+ for (const action of config.setupActions){
29509
+ map[action.type] = action.versionFileKey;
29510
+ }
29511
+ return map;
29512
+ }
29487
29513
 
29488
29514
  ;// CONCATENATED MODULE: ../core/src/lib/copilot-setup-config.ts
29489
29515
  /**
@@ -29611,29 +29637,8 @@ const CopilotSetupConfigSchema = schemas_object({
29611
29637
  *
29612
29638
  * This function is retained for backwards compatibility but is a no-op
29613
29639
  * because configuration is no longer cached at module scope.
29614
- */ function resetCopilotSetupConfigCache() {
29615
- // no in-memory cache to reset
29616
- }
29617
- /**
29618
- * Gets a version file type to action mapping from config.
29619
- * Returns a partial record as not all types may be configured.
29620
- */ function getVersionTypeToActionMap(config) {
29621
- const map = {};
29622
- for (const action of config.setupActions){
29623
- map[action.type] = action.action;
29624
- }
29625
- return map;
29626
- }
29627
- /**
29628
- * Gets a version file type to config key mapping from config.
29629
- * Returns a partial record as not all types may be configured.
29630
- */ function getVersionFileConfigKeyMap(config) {
29631
- const map = {};
29632
- for (const action of config.setupActions){
29633
- map[action.type] = action.versionFileKey;
29634
- }
29635
- return map;
29636
- }
29640
+ */ function resetCopilotSetupConfigCache() {}
29641
+
29637
29642
  /**
29638
29643
  * Gets a filename to version type mapping from config.
29639
29644
  */ function getVersionFilenameToTypeMap(config) {
@@ -29995,15 +30000,12 @@ function defaultExec(command, args, options) {
29995
30000
  * File system implementation of instruction analysis gateway
29996
30001
  */ class FileSystemInstructionAnalysisGateway {
29997
30002
  async analyzeCoverage(targetDir, scripts, tools) {
29998
- // Find all instruction files
29999
30003
  const instructionFiles = await this.findInstructionFiles(targetDir);
30000
- // Read and search instruction content
30001
30004
  const references = [];
30002
30005
  const documentedTargets = new Set();
30003
30006
  for (const file of instructionFiles){
30004
30007
  const content = await (0,promises_.readFile)(file, "utf-8");
30005
30008
  const lines = content.split("\n");
30006
- // Check for script references (e.g., "npm test", "npm run build")
30007
30009
  for (const script of scripts){
30008
30010
  const scriptRefs = this.findReferencesInContent(script.name, content, lines, file, targetDir);
30009
30011
  if (scriptRefs.length > 0) {
@@ -30011,7 +30013,6 @@ function defaultExec(command, args, options) {
30011
30013
  documentedTargets.add(script.name);
30012
30014
  }
30013
30015
  }
30014
- // Check for tool references (e.g., "mise run test", "biome check")
30015
30016
  for (const tool of tools){
30016
30017
  const toolRefs = this.findReferencesInContent(tool.name, content, lines, file, targetDir);
30017
30018
  if (toolRefs.length > 0) {
@@ -30020,14 +30021,12 @@ function defaultExec(command, args, options) {
30020
30021
  }
30021
30022
  }
30022
30023
  }
30023
- // Filter mandatory scripts/tools
30024
30024
  const mandatoryScripts = scripts.filter((s)=>s.isMandatory);
30025
30025
  const mandatoryTools = tools.filter((t)=>t.isMandatory);
30026
30026
  const allMandatory = [
30027
30027
  ...mandatoryScripts,
30028
30028
  ...mandatoryTools
30029
30029
  ];
30030
- // Categorize as missing or documented
30031
30030
  const missingInInstructions = allMandatory.filter((item)=>!documentedTargets.has(item.name));
30032
30031
  const documentedInInstructions = allMandatory.filter((item)=>documentedTargets.has(item.name));
30033
30032
  const totalMandatory = allMandatory.length;
@@ -30046,12 +30045,10 @@ function defaultExec(command, args, options) {
30046
30045
  }
30047
30046
  async findInstructionFiles(targetDir) {
30048
30047
  const files = [];
30049
- // Check for .github/copilot-instructions.md
30050
30048
  const copilotInstructions = (0,external_node_path_.join)(targetDir, ".github", "copilot-instructions.md");
30051
30049
  if (await file_system_utils_fileExists(copilotInstructions)) {
30052
30050
  files.push(copilotInstructions);
30053
30051
  }
30054
- // Check for .github/instructions/*.md
30055
30052
  const instructionsDir = (0,external_node_path_.join)(targetDir, ".github", "instructions");
30056
30053
  if (await file_system_utils_fileExists(instructionsDir)) {
30057
30054
  try {
@@ -30061,31 +30058,20 @@ function defaultExec(command, args, options) {
30061
30058
  files.push((0,external_node_path_.join)(instructionsDir, file));
30062
30059
  }
30063
30060
  }
30064
- } catch {
30065
- // Skip directory if we can't read it (e.g., permissions issues)
30066
- // Similar to how workflow parsing errors are handled
30067
- }
30061
+ } catch {}
30068
30062
  }
30069
30063
  return files;
30070
30064
  }
30071
30065
  findReferencesInContent(target, content, lines, file, targetDir) {
30072
30066
  const references = [];
30073
- // Build a case-insensitive, word-boundary-aware pattern for the target.
30074
- // This reduces false positives from simple substring matches like
30075
- // "test" in "testing" or "latest", while still matching common
30076
- // separators such as spaces, punctuation, etc.
30077
30067
  const escapedTarget = target.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
30078
30068
  const targetPattern = new RegExp(`(?:^|[^\\w])(${escapedTarget})(?=$|[^\\w])`, "i");
30079
- // Fast path: skip line-by-line processing if the target pattern
30080
- // never appears in the full content.
30081
30069
  if (!targetPattern.test(content)) {
30082
30070
  return references;
30083
30071
  }
30084
- // Find line numbers where target appears
30085
30072
  for(let i = 0; i < lines.length; i++){
30086
30073
  const line = lines[i];
30087
30074
  if (targetPattern.test(line)) {
30088
- // Get context (line before and after if available)
30089
30075
  const contextLines = [];
30090
30076
  if (i > 0) contextLines.push(lines[i - 1]);
30091
30077
  contextLines.push(line);
@@ -31797,47 +31783,78 @@ const MAX_NPMRC_BYTES = (/* unused pure expression or super */ null && (64 * 102
31797
31783
 
31798
31784
 
31799
31785
 
31786
+
31787
+ // 1 MB — covers even the largest real-world manifests
31788
+ const MAX_PACKAGE_JSON_BYTES = 1024 * 1024;
31789
+ const PackageJsonSchema = schemas_object({
31790
+ scripts: record(schemas_string(), schemas_string()).optional()
31791
+ });
31800
31792
  /**
31801
31793
  * File system implementation of script discovery gateway
31802
31794
  */ class FileSystemScriptDiscoveryGateway {
31795
+ constructor(logger){
31796
+ this.logger = logger ?? dist_consola;
31797
+ }
31798
+ logger;
31803
31799
  async discoverScripts(targetDir) {
31804
31800
  const packageJsonPath = (0,external_node_path_.join)(targetDir, "package.json");
31805
- if (!await file_system_utils_fileExists(packageJsonPath)) {
31801
+ let content;
31802
+ try {
31803
+ content = await file_system_utils_readFileNoFollow(packageJsonPath, MAX_PACKAGE_JSON_BYTES);
31804
+ } catch (error) {
31805
+ const code = error instanceof Error && "code" in error ? error.code : undefined;
31806
+ if (code !== "ENOENT") {
31807
+ this.logger.warn(`script-discovery: could not read ${JSON.stringify(packageJsonPath)}: ${JSON.stringify(error instanceof Error ? error.message : String(error))}`);
31808
+ }
31806
31809
  return [];
31807
31810
  }
31811
+ let parsed;
31808
31812
  try {
31809
- const content = await (0,promises_.readFile)(packageJsonPath, "utf-8");
31810
- const packageJson = JSON.parse(content);
31811
- if (!packageJson.scripts) {
31813
+ parsed = JSON.parse(content);
31814
+ } catch (e) {
31815
+ if (e instanceof SyntaxError) {
31816
+ this.logger.warn(`script-discovery: ${JSON.stringify(packageJsonPath)} contains invalid JSON — ${JSON.stringify(e.message)}`);
31812
31817
  return [];
31813
31818
  }
31814
- const scripts = [];
31815
- for (const [name, command] of Object.entries(packageJson.scripts)){
31816
- const phase = determineScriptPhase(name, command);
31817
- const isMandatory = isScriptMandatory(phase);
31818
- scripts.push({
31819
- name,
31820
- command,
31821
- phase,
31822
- isMandatory
31823
- });
31824
- }
31825
- return scripts;
31826
- } catch {
31827
- // If package.json is malformed or cannot be parsed, return empty array
31819
+ throw e;
31820
+ }
31821
+ const parseResult = PackageJsonSchema.safeParse(parsed);
31822
+ if (!parseResult.success) {
31823
+ this.logger.warn(`script-discovery: ${JSON.stringify(packageJsonPath)} has an unexpected structure — scripts field must be a record of strings`);
31824
+ return [];
31825
+ }
31826
+ if (!parseResult.data.scripts) {
31828
31827
  return [];
31829
31828
  }
31829
+ const scripts = [];
31830
+ for (const [name, command] of Object.entries(parseResult.data.scripts)){
31831
+ const phase = determineScriptPhase(name, command);
31832
+ const isMandatory = isScriptMandatory(phase);
31833
+ scripts.push({
31834
+ name,
31835
+ command,
31836
+ phase,
31837
+ isMandatory
31838
+ });
31839
+ }
31840
+ return scripts;
31830
31841
  }
31831
31842
  }
31832
31843
  /**
31833
31844
  * Creates and returns the default script discovery gateway
31834
- */ function createScriptDiscoveryGateway() {
31835
- return new FileSystemScriptDiscoveryGateway();
31845
+ */ function createScriptDiscoveryGateway(logger) {
31846
+ return new FileSystemScriptDiscoveryGateway(logger);
31836
31847
  }
31837
31848
  /**
31838
31849
  * Creates a FeedbackLoopCommandsGateway that discovers mandatory commands from package.json scripts.
31839
- */ function createFeedbackLoopCommandsGateway(scriptGateway) {
31840
- const gateway = scriptGateway ?? createScriptDiscoveryGateway();
31850
+ *
31851
+ * @param scriptGateway - Optional gateway implementation. If omitted, a default
31852
+ * `FileSystemScriptDiscoveryGateway` is created using `logger`.
31853
+ * @param logger - Optional logger for the default gateway. Only used when
31854
+ * `scriptGateway` is omitted; if a custom `scriptGateway` is supplied, its
31855
+ * own logger configuration applies and this parameter is ignored.
31856
+ */ function createFeedbackLoopCommandsGateway(scriptGateway, logger) {
31857
+ const gateway = scriptGateway ?? createScriptDiscoveryGateway(logger);
31841
31858
  return {
31842
31859
  async getMandatoryCommands (targetDir) {
31843
31860
  const scripts = await gateway.discoverScripts(targetDir);
@@ -31887,6 +31904,56 @@ const MAX_NPMRC_BYTES = (/* unused pure expression or super */ null && (64 * 102
31887
31904
 
31888
31905
  // EXTERNAL MODULE: ../../node_modules/yaml/dist/index.js
31889
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
+
31890
31957
  ;// CONCATENATED MODULE: ../core/src/gateways/skill-lint-gateway.ts
31891
31958
  /**
31892
31959
  * Gateway for skill lint file system operations.
@@ -31900,7 +31967,8 @@ var yaml_dist = __webpack_require__(3519);
31900
31967
  * Skill directory locations to search for SKILL.md files.
31901
31968
  */ const SKILL_DIRECTORIES = [
31902
31969
  (0,external_node_path_.join)(".github", "skills"),
31903
- (0,external_node_path_.join)(".claude", "skills")
31970
+ (0,external_node_path_.join)(".claude", "skills"),
31971
+ (0,external_node_path_.join)(".agents", "skills")
31904
31972
  ];
31905
31973
  /**
31906
31974
  * File system implementation of the skill lint gateway.
@@ -31970,41 +32038,7 @@ var yaml_dist = __webpack_require__(3519);
31970
32038
  return readFileNoFollow(filePath, MAX_SKILL_FILE_BYTES);
31971
32039
  }
31972
32040
  parseFrontmatter(content) {
31973
- const lines = content.split("\n");
31974
- if (lines[0]?.trim() !== "---") {
31975
- return null;
31976
- }
31977
- let endIndex = -1;
31978
- for(let i = 1; i < lines.length; i++){
31979
- if (lines[i]?.trim() === "---") {
31980
- endIndex = i;
31981
- break;
31982
- }
31983
- }
31984
- if (endIndex === -1) {
31985
- return null;
31986
- }
31987
- const yamlContent = lines.slice(1, endIndex).join("\n");
31988
- let data;
31989
- try {
31990
- const parsed = parseYaml(yamlContent);
31991
- data = parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
31992
- } catch {
31993
- return null;
31994
- }
31995
- const fieldLines = new Map();
31996
- for(let i = 1; i < endIndex; i++){
31997
- // Match YAML top-level field names: non-whitespace start, any chars except colon, then colon+space
31998
- const match = lines[i]?.match(/^([^\s:][^:]*?):\s/);
31999
- if (match?.[1]) {
32000
- fieldLines.set(match[1], i + 1);
32001
- }
32002
- }
32003
- return {
32004
- data: data ?? {},
32005
- fieldLines,
32006
- frontmatterStartLine: 1
32007
- };
32041
+ return parseFrontmatter(content);
32008
32042
  }
32009
32043
  }
32010
32044
  /**
@@ -32039,9 +32073,7 @@ var yaml_dist = __webpack_require__(3519);
32039
32073
  const workflow = (0,yaml_dist/* .parse */.qg)(content);
32040
32074
  const tools = this.extractToolsFromWorkflow(workflow, file);
32041
32075
  allTools.push(...tools);
32042
- } catch {
32043
- // Skip files that can't be parsed as valid YAML
32044
- }
32076
+ } catch {}
32045
32077
  }
32046
32078
  return this.deduplicateTools(allTools);
32047
32079
  }
@@ -32069,7 +32101,6 @@ var yaml_dist = __webpack_require__(3519);
32069
32101
  const stepObj = step;
32070
32102
  const run = stepObj.run;
32071
32103
  if (typeof run === "string") {
32072
- // Extract tools from run commands
32073
32104
  const extractedTools = this.extractToolsFromRunCommand(run, sourceFile);
32074
32105
  tools.push(...extractedTools);
32075
32106
  }
@@ -32079,35 +32110,24 @@ var yaml_dist = __webpack_require__(3519);
32079
32110
  }
32080
32111
  extractToolsFromRunCommand(runCommand, sourceFile) {
32081
32112
  const tools = [];
32082
- // Split by newlines and pipe tokens with surrounding whitespace to handle
32083
- // multi-line and piped commands without breaking on constructs like "cmd || true"
32084
32113
  const commands = runCommand.split(/\n|\s\|\s/).map((c)=>c.trim()).filter((c)=>c.length > 0 && !c.startsWith("#"));
32085
32114
  for (const command of commands){
32086
- // Extract the base command (first word)
32087
32115
  const parts = command.split(/\s+/);
32088
32116
  const baseCommand = parts[0];
32089
- // Skip shell built-ins and common utilities
32090
32117
  if (this.isShellBuiltin(baseCommand)) {
32091
32118
  continue;
32092
32119
  }
32093
- // Determine tool name and full command
32094
32120
  let toolName;
32095
32121
  const fullCommand = command;
32096
- // Handle special cases like "npm run", "mise run", etc.
32097
32122
  if (parts.length >= 2 && (baseCommand === "npm" || baseCommand === "mise") && parts[1] === "run") {
32098
32123
  if (parts.length >= 3 && parts[2]) {
32099
- // "npm run test" -> name: "npm run test"
32100
32124
  toolName = parts.slice(0, 3).join(" ");
32101
32125
  } else {
32102
- // Handle commands like "npm run" without a script name
32103
32126
  toolName = parts.slice(0, 2).join(" ");
32104
32127
  }
32105
32128
  } else if (parts.length >= 2) {
32106
- // For most tools, include the subcommand for better specificity
32107
- // e.g., "npm test", "npx biome", "pnpm lint"
32108
32129
  toolName = parts.slice(0, 2).join(" ");
32109
32130
  } else {
32110
- // Fallback to the base command if no subcommand is present
32111
32131
  toolName = baseCommand;
32112
32132
  }
32113
32133
  const phase = this.determineToolPhase(toolName, fullCommand);
@@ -32146,13 +32166,11 @@ var yaml_dist = __webpack_require__(3519);
32146
32166
  return builtins.includes(command);
32147
32167
  }
32148
32168
  determineToolPhase(toolName, fullCommand) {
32149
- // Use the same logic as script phase determination
32150
32169
  return determineScriptPhase(toolName, fullCommand);
32151
32170
  }
32152
32171
  deduplicateTools(tools) {
32153
32172
  const seen = new Map();
32154
32173
  for (const tool of tools){
32155
- // Use full command as key for deduplication
32156
32174
  const key = tool.fullCommand;
32157
32175
  if (!seen.has(key)) {
32158
32176
  seen.set(key, tool);
@@ -32409,9 +32427,7 @@ class FileSystemWorkflowGateway {
32409
32427
  const workflow = (0,yaml_dist/* .parse */.qg)(content);
32410
32428
  const candidates = extractSetupStepsFromWorkflow(workflow, config.setupActionPatterns);
32411
32429
  allCandidates.push(...candidates);
32412
- } catch {
32413
- // Skip unreadable or malformed YAML workflow files while continuing scan.
32414
- }
32430
+ } catch {}
32415
32431
  }
32416
32432
  return deduplicateCandidates(allCandidates);
32417
32433
  }
@@ -32448,8 +32464,7 @@ function createWorkflowGateway(cwd) {
32448
32464
  ;// CONCATENATED MODULE: ../core/src/gateways/workflow-gateway.ts
32449
32465
  /**
32450
32466
  * Gateway interface for GitHub Actions workflow operations.
32451
- */ // Re-export implementation and factory from the implementation file
32452
-
32467
+ */
32453
32468
 
32454
32469
  ;// CONCATENATED MODULE: ../core/src/gateways/index.ts
32455
32470
  /**
@@ -52758,7 +52773,6 @@ Example resolved format: actions/setup-node@1a2b3c4d5e6f # v4.0.0`;
52758
52773
  * This module handles the logic of determining which GitHub Actions
52759
52774
  * setup steps should be added based on detected version files and package managers.
52760
52775
  */
52761
-
52762
52776
  /**
52763
52777
  * Creates an ActionVersionPort backed by a static version map.
52764
52778
  */ function createActionVersionPort(versionMap) {
@@ -53632,11 +53646,8 @@ const workflow_generator_defaultActionVersionPort = createActionVersionPort(work
53632
53646
  if (!input.targetDir) {
53633
53647
  throw new Error("Target directory is required");
53634
53648
  }
53635
- // Discover scripts from package.json
53636
53649
  const scripts = await this.scriptGateway.discoverScripts(input.targetDir);
53637
- // Discover tools from GitHub Actions workflows
53638
53650
  const tools = await this.toolGateway.discoverTools(input.targetDir);
53639
- // Detect package manager
53640
53651
  const packageManagers = await this.packageManagerGateway.detectPackageManagers(input.targetDir);
53641
53652
  const primaryPackageManager = packageManagers.length > 0 ? packageManagers[0].type : undefined;
53642
53653
  const feedbackLoops = {
@@ -53897,14 +53908,11 @@ const workflow_generator_defaultActionVersionPort = createActionVersionPort(work
53897
53908
  if (!input.targetDir) {
53898
53909
  throw new Error("Target directory is required");
53899
53910
  }
53900
- // First, discover all feedback loops
53901
53911
  const discoveryResult = await this.discoverFeedbackLoops.execute({
53902
53912
  targetDir: input.targetDir
53903
53913
  });
53904
53914
  const { scripts, tools, packageManager } = discoveryResult.feedbackLoops;
53905
- // Analyze instruction coverage
53906
53915
  const coverage = await this.instructionGateway.analyzeCoverage(input.targetDir, scripts, tools);
53907
- // Generate suggestions for missing documentation
53908
53916
  const suggestions = this.generateSuggestions(coverage, packageManager || "npm");
53909
53917
  return {
53910
53918
  coverage,
@@ -53920,22 +53928,18 @@ const workflow_generator_defaultActionVersionPort = createActionVersionPort(work
53920
53928
  }
53921
53929
  suggestions.push(`⚠️ ${coverage.missingInInstructions.length} mandatory feedback loop(s) are not documented:`);
53922
53930
  suggestions.push("");
53923
- // Group by phase
53924
53931
  const byPhase = new Map();
53925
53932
  for (const item of coverage.missingInInstructions){
53926
53933
  const existing = byPhase.get(item.phase) || [];
53927
53934
  existing.push(item);
53928
53935
  byPhase.set(item.phase, existing);
53929
53936
  }
53930
- // Generate suggestions per phase
53931
53937
  for (const [phase, items] of byPhase.entries()){
53932
53938
  suggestions.push(`${phase.toUpperCase()} phase:`);
53933
53939
  for (const item of items){
53934
53940
  if ("command" in item) {
53935
- // It's a script
53936
53941
  suggestions.push(` - Document "${packageManager} run ${item.name}" (runs: ${item.command})`);
53937
53942
  } else {
53938
- // It's a tool
53939
53943
  suggestions.push(` - Document "${item.fullCommand}"`);
53940
53944
  }
53941
53945
  }
@@ -63810,4 +63814,4 @@ if (installedChunkData !== 0) { // 0 means "already installed".'
63810
63814
  // module factories are used so entry inlining is disabled
63811
63815
  // startup
63812
63816
  // Load entry module and return exports
63813
- var __webpack_exports__ = __webpack_require__(5714);
63817
+ var __webpack_exports__ = __webpack_require__(832);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lousy-agents/mcp",
3
- "version": "5.12.2",
3
+ "version": "5.13.1",
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": {
@@ -38,7 +38,7 @@
38
38
  "dependencies": {
39
39
  "@modelcontextprotocol/sdk": "1.29.0",
40
40
  "yaml": "2.8.4",
41
- "zod": "4.4.2"
41
+ "zod": "4.4.3"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@lousy-agents/core": "*"