typegraph-mcp 0.9.22 → 0.9.24

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/check.ts CHANGED
@@ -371,8 +371,10 @@ export async function main(configOverride?: TypegraphConfig): Promise<CheckResul
371
371
 
372
372
  // 11. ESLint ignores (only when typegraph-mcp is embedded inside the project)
373
373
  if (toolIsEmbedded) {
374
- const eslintConfigPath = path.resolve(projectRoot, "eslint.config.mjs");
375
- if (fs.existsSync(eslintConfigPath)) {
374
+ const eslintConfigNames = ["eslint.config.mjs", "eslint.config.js", "eslint.config.ts", "eslint.config.cjs"];
375
+ const eslintConfigFile = eslintConfigNames.find((name) => fs.existsSync(path.resolve(projectRoot, name)));
376
+ if (eslintConfigFile) {
377
+ const eslintConfigPath = path.resolve(projectRoot, eslintConfigFile);
376
378
  const eslintContent = fs.readFileSync(eslintConfigPath, "utf-8");
377
379
  // Determine the parent directory (e.g. "plugins") for the ignore pattern
378
380
  const parentDir = path.basename(path.dirname(toolDir));
@@ -384,11 +386,11 @@ export async function main(configOverride?: TypegraphConfig): Promise<CheckResul
384
386
  } else {
385
387
  fail(
386
388
  `ESLint missing ignore: "${parentDir}/**"`,
387
- `Add to the ignores array in eslint.config.mjs:\n "${parentDir}/**",`
389
+ `Add to the ignores array in ${eslintConfigFile}:\n "${parentDir}/**",`
388
390
  );
389
391
  }
390
392
  } else {
391
- skip("ESLint config check (no eslint.config.mjs)");
393
+ skip("ESLint config check (no eslint flat config found)");
392
394
  }
393
395
  } else {
394
396
  skip("ESLint config check (typegraph-mcp is external to project)");
package/cli.ts CHANGED
@@ -62,6 +62,7 @@ const AGENTS: Record<AgentId, AgentDef> = {
62
62
  "scripts/ensure-deps.sh",
63
63
  "commands/check.md",
64
64
  "commands/test.md",
65
+ "commands/bench.md",
65
66
  ],
66
67
  agentFile: "CLAUDE.md",
67
68
  needsAgentsSkills: false,
@@ -362,6 +363,51 @@ function ensureTsconfigExclude(projectRoot: string): void {
362
363
  }
363
364
  }
364
365
 
366
+ // ─── ESLint Ignore ───────────────────────────────────────────────────────────
367
+
368
+ function ensureEslintIgnore(projectRoot: string): void {
369
+ const eslintConfigNames = ["eslint.config.mjs", "eslint.config.js", "eslint.config.ts", "eslint.config.cjs"];
370
+ const eslintConfigFile = eslintConfigNames.find((name) => fs.existsSync(path.resolve(projectRoot, name)));
371
+ if (!eslintConfigFile) return;
372
+ const eslintConfigPath = path.resolve(projectRoot, eslintConfigFile);
373
+
374
+ try {
375
+ const raw = fs.readFileSync(eslintConfigPath, "utf-8");
376
+ const pattern = /["']plugins\/\*\*["']/;
377
+ if (pattern.test(raw)) return; // Already ignored
378
+
379
+ // Strategy 1: Append to an existing ignores array
380
+ const ignoresArrayRe = /(ignores\s*:\s*\[)([\s\S]*?)(\])/;
381
+ const match = raw.match(ignoresArrayRe);
382
+ if (match) {
383
+ const updated = raw.replace(ignoresArrayRe, (_m, open, items, close) => {
384
+ const trimmed = items.trimEnd();
385
+ const needsComma = trimmed.length > 0 && !trimmed.endsWith(",");
386
+ return `${open}${items.trimEnd()}${needsComma ? "," : ""} "plugins/**"${close}`;
387
+ });
388
+ fs.writeFileSync(eslintConfigPath, updated);
389
+ p.log.success(`Added "plugins/**" to ${eslintConfigFile} ignores`);
390
+ return;
391
+ }
392
+
393
+ // Strategy 2: Insert a new ignores object at the start of the exported array
394
+ // Matches: export default [ or export default tseslint.config(
395
+ const exportArrayRe = /(export\s+default\s+(?:\w+\.config\(|\[))\s*\n?/;
396
+ if (exportArrayRe.test(raw)) {
397
+ const updated = raw.replace(exportArrayRe, (m) => {
398
+ return `${m} { ignores: ["plugins/**"] },\n`;
399
+ });
400
+ fs.writeFileSync(eslintConfigPath, updated);
401
+ p.log.success(`Added "plugins/**" to ${eslintConfigFile} ignores`);
402
+ return;
403
+ }
404
+
405
+ p.log.warn(`Could not patch ${eslintConfigFile} — manually add "plugins/**" to the ignores array`);
406
+ } catch {
407
+ p.log.warn(`Could not update ${eslintConfigFile} — manually add "plugins/**" to the ignores array`);
408
+ }
409
+ }
410
+
365
411
  // ─── Agent Selection ─────────────────────────────────────────────────────────
366
412
 
367
413
  function detectAgents(projectRoot: string): AgentId[] {
@@ -564,7 +610,10 @@ async function setup(yes: boolean): Promise<void> {
564
610
  // 8. Ensure plugins/ is excluded from tsconfig
565
611
  ensureTsconfigExclude(projectRoot);
566
612
 
567
- // 9. Verification
613
+ // 9. Ensure plugins/ is ignored by ESLint
614
+ ensureEslintIgnore(projectRoot);
615
+
616
+ // 10. Verification
568
617
  await runVerification(targetDir, selectedAgents);
569
618
  }
570
619
 
package/dist/check.js CHANGED
@@ -663,8 +663,10 @@ async function main(configOverride) {
663
663
  );
664
664
  }
665
665
  if (toolIsEmbedded) {
666
- const eslintConfigPath = path3.resolve(projectRoot, "eslint.config.mjs");
667
- if (fs2.existsSync(eslintConfigPath)) {
666
+ const eslintConfigNames = ["eslint.config.mjs", "eslint.config.js", "eslint.config.ts", "eslint.config.cjs"];
667
+ const eslintConfigFile = eslintConfigNames.find((name) => fs2.existsSync(path3.resolve(projectRoot, name)));
668
+ if (eslintConfigFile) {
669
+ const eslintConfigPath = path3.resolve(projectRoot, eslintConfigFile);
668
670
  const eslintContent = fs2.readFileSync(eslintConfigPath, "utf-8");
669
671
  const parentDir = path3.basename(path3.dirname(toolDir));
670
672
  const parentIgnorePattern = new RegExp(`["']${parentDir}\\/\\*\\*["']`);
@@ -674,12 +676,12 @@ async function main(configOverride) {
674
676
  } else {
675
677
  fail(
676
678
  `ESLint missing ignore: "${parentDir}/**"`,
677
- `Add to the ignores array in eslint.config.mjs:
679
+ `Add to the ignores array in ${eslintConfigFile}:
678
680
  "${parentDir}/**",`
679
681
  );
680
682
  }
681
683
  } else {
682
- skip("ESLint config check (no eslint.config.mjs)");
684
+ skip("ESLint config check (no eslint flat config found)");
683
685
  }
684
686
  } else {
685
687
  skip("ESLint config check (typegraph-mcp is external to project)");
package/dist/cli.js CHANGED
@@ -670,8 +670,10 @@ async function main(configOverride) {
670
670
  );
671
671
  }
672
672
  if (toolIsEmbedded) {
673
- const eslintConfigPath = path3.resolve(projectRoot3, "eslint.config.mjs");
674
- if (fs2.existsSync(eslintConfigPath)) {
673
+ const eslintConfigNames = ["eslint.config.mjs", "eslint.config.js", "eslint.config.ts", "eslint.config.cjs"];
674
+ const eslintConfigFile = eslintConfigNames.find((name) => fs2.existsSync(path3.resolve(projectRoot3, name)));
675
+ if (eslintConfigFile) {
676
+ const eslintConfigPath = path3.resolve(projectRoot3, eslintConfigFile);
675
677
  const eslintContent = fs2.readFileSync(eslintConfigPath, "utf-8");
676
678
  const parentDir = path3.basename(path3.dirname(toolDir));
677
679
  const parentIgnorePattern = new RegExp(`["']${parentDir}\\/\\*\\*["']`);
@@ -681,12 +683,12 @@ async function main(configOverride) {
681
683
  } else {
682
684
  fail(
683
685
  `ESLint missing ignore: "${parentDir}/**"`,
684
- `Add to the ignores array in eslint.config.mjs:
686
+ `Add to the ignores array in ${eslintConfigFile}:
685
687
  "${parentDir}/**",`
686
688
  );
687
689
  }
688
690
  } else {
689
- skip("ESLint config check (no eslint.config.mjs)");
691
+ skip("ESLint config check (no eslint flat config found)");
690
692
  }
691
693
  } else {
692
694
  skip("ESLint config check (typegraph-mcp is external to project)");
@@ -2815,7 +2817,8 @@ var AGENTS = {
2815
2817
  "hooks/hooks.json",
2816
2818
  "scripts/ensure-deps.sh",
2817
2819
  "commands/check.md",
2818
- "commands/test.md"
2820
+ "commands/test.md",
2821
+ "commands/bench.md"
2819
2822
  ],
2820
2823
  agentFile: "CLAUDE.md",
2821
2824
  needsAgentsSkills: false,
@@ -3055,6 +3058,42 @@ function ensureTsconfigExclude(projectRoot3) {
3055
3058
  p.log.warn('Could not update tsconfig.json \u2014 manually add "plugins/**" to the exclude array to prevent build errors');
3056
3059
  }
3057
3060
  }
3061
+ function ensureEslintIgnore(projectRoot3) {
3062
+ const eslintConfigNames = ["eslint.config.mjs", "eslint.config.js", "eslint.config.ts", "eslint.config.cjs"];
3063
+ const eslintConfigFile = eslintConfigNames.find((name) => fs8.existsSync(path9.resolve(projectRoot3, name)));
3064
+ if (!eslintConfigFile) return;
3065
+ const eslintConfigPath = path9.resolve(projectRoot3, eslintConfigFile);
3066
+ try {
3067
+ const raw = fs8.readFileSync(eslintConfigPath, "utf-8");
3068
+ const pattern = /["']plugins\/\*\*["']/;
3069
+ if (pattern.test(raw)) return;
3070
+ const ignoresArrayRe = /(ignores\s*:\s*\[)([\s\S]*?)(\])/;
3071
+ const match = raw.match(ignoresArrayRe);
3072
+ if (match) {
3073
+ const updated = raw.replace(ignoresArrayRe, (_m, open, items, close) => {
3074
+ const trimmed = items.trimEnd();
3075
+ const needsComma = trimmed.length > 0 && !trimmed.endsWith(",");
3076
+ return `${open}${items.trimEnd()}${needsComma ? "," : ""} "plugins/**"${close}`;
3077
+ });
3078
+ fs8.writeFileSync(eslintConfigPath, updated);
3079
+ p.log.success(`Added "plugins/**" to ${eslintConfigFile} ignores`);
3080
+ return;
3081
+ }
3082
+ const exportArrayRe = /(export\s+default\s+(?:\w+\.config\(|\[))\s*\n?/;
3083
+ if (exportArrayRe.test(raw)) {
3084
+ const updated = raw.replace(exportArrayRe, (m) => {
3085
+ return `${m} { ignores: ["plugins/**"] },
3086
+ `;
3087
+ });
3088
+ fs8.writeFileSync(eslintConfigPath, updated);
3089
+ p.log.success(`Added "plugins/**" to ${eslintConfigFile} ignores`);
3090
+ return;
3091
+ }
3092
+ p.log.warn(`Could not patch ${eslintConfigFile} \u2014 manually add "plugins/**" to the ignores array`);
3093
+ } catch {
3094
+ p.log.warn(`Could not update ${eslintConfigFile} \u2014 manually add "plugins/**" to the ignores array`);
3095
+ }
3096
+ }
3058
3097
  function detectAgents(projectRoot3) {
3059
3098
  return AGENT_IDS.filter((id) => AGENTS[id].detect(projectRoot3));
3060
3099
  }
@@ -3199,6 +3238,7 @@ async function setup(yes2) {
3199
3238
  await setupAgentInstructions(projectRoot3, selectedAgents);
3200
3239
  registerMcpServers(projectRoot3, selectedAgents);
3201
3240
  ensureTsconfigExclude(projectRoot3);
3241
+ ensureEslintIgnore(projectRoot3);
3202
3242
  await runVerification(targetDir, selectedAgents);
3203
3243
  }
3204
3244
  async function removePlugin(projectRoot3, pluginDir) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "typegraph-mcp",
3
- "version": "0.9.22",
3
+ "version": "0.9.24",
4
4
  "description": "Type-aware codebase navigation for AI coding agents — 14 MCP tools powered by tsserver + oxc",
5
5
  "license": "MIT",
6
6
  "type": "module",