@danielblomma/cortex-mcp 2.2.4 → 2.4.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.
@@ -180,15 +180,33 @@ fi
180
180
 
181
181
  # Quick runtime import check
182
182
  if [[ -f "$MCP_DIR/dist/server.js" ]] && [[ -d "$MCP_DIR/node_modules" ]]; then
183
- MCP_CHECK=$(cd "$REPO_ROOT" && timeout 10 node -e '
184
- const start = Date.now();
185
- try {
186
- require("./.context/mcp/dist/graph.js");
187
- console.log("ok " + (Date.now() - start));
188
- } catch(e) {
189
- console.log("fail " + e.message);
183
+ MCP_CHECK=$(cd "$REPO_ROOT" && node -e '
184
+ const { spawnSync } = require("node:child_process");
185
+ const timeoutMs = Number(process.env.CORTEX_DOCTOR_GRAPH_TIMEOUT_MS || 30000);
186
+ const probe = [
187
+ "const start = Date.now();",
188
+ "try {",
189
+ " require(\"./.context/mcp/dist/graph.js\");",
190
+ " console.log(\"ok \" + (Date.now() - start));",
191
+ "} catch (e) {",
192
+ " console.log(\"fail \" + (e && e.message ? e.message : String(e)));",
193
+ " process.exitCode = 1;",
194
+ "}"
195
+ ].join("\n");
196
+ const result = spawnSync(process.execPath, ["-e", probe], {
197
+ encoding: "utf8",
198
+ stdio: ["ignore", "pipe", "pipe"],
199
+ timeout: timeoutMs
200
+ });
201
+ if (result.error && result.error.code === "ETIMEDOUT") {
202
+ console.log("fail timeout after " + timeoutMs + "ms");
203
+ } else if (result.error) {
204
+ console.log("fail " + result.error.message);
205
+ } else {
206
+ const lines = String(result.stdout || "").trim().split(/\r?\n/).filter(Boolean);
207
+ console.log(lines[lines.length - 1] || ("fail exit " + (result.status ?? "unknown")));
190
208
  }
191
- ' 2>/dev/null || echo "fail timeout")
209
+ ' 2>/dev/null || echo "fail graph check crashed")
192
210
  if [[ "$MCP_CHECK" == ok* ]]; then
193
211
  MS="${MCP_CHECK#ok }"
194
212
  pass "Graph module loads (${MS}ms)"
@@ -457,11 +457,11 @@ function parseRules(rulesText) {
457
457
  function walkDirectory(directoryPath, files) {
458
458
  const entries = fs.readdirSync(directoryPath, { withFileTypes: true });
459
459
  for (const entry of entries) {
460
- if (entry.isDirectory() && SKIP_DIRECTORIES.has(entry.name)) {
460
+ const absolutePath = path.join(directoryPath, entry.name);
461
+ if (entry.isDirectory() && shouldSkipDirectory(absolutePath, entry.name)) {
461
462
  continue;
462
463
  }
463
464
 
464
- const absolutePath = path.join(directoryPath, entry.name);
465
465
  if (entry.isDirectory()) {
466
466
  walkDirectory(absolutePath, files);
467
467
  continue;
@@ -473,10 +473,40 @@ function walkDirectory(directoryPath, files) {
473
473
  }
474
474
  }
475
475
 
476
+ function shouldSkipDirectory(absolutePath, entryName) {
477
+ if (entryName === "bin" && path.resolve(path.dirname(absolutePath)) === REPO_ROOT) {
478
+ return false;
479
+ }
480
+ return SKIP_DIRECTORIES.has(entryName);
481
+ }
482
+
483
+ function normalizeSourcePrefix(sourcePath) {
484
+ const source = toPosixPath(sourcePath).replace(/^\.\/+/, "").replace(/\/+$/, "");
485
+ return source === "." ? "" : source;
486
+ }
487
+
488
+ function normalizeRelativePath(relPath) {
489
+ return toPosixPath(relPath).replace(/^\.\/+/, "").replace(/\/+$/, "");
490
+ }
491
+
492
+ function hasSkippedDirectorySegment(relPath) {
493
+ const parts = normalizeRelativePath(relPath).split("/").filter(Boolean);
494
+ return parts.some((part, index) => {
495
+ if (part === "bin" && index === 0) {
496
+ return false;
497
+ }
498
+ return SKIP_DIRECTORIES.has(part);
499
+ });
500
+ }
501
+
476
502
  function hasSourcePrefix(relPath, sourcePaths) {
503
+ const normalizedRelPath = normalizeRelativePath(relPath);
504
+ if (!normalizedRelPath || hasSkippedDirectorySegment(normalizedRelPath)) {
505
+ return false;
506
+ }
477
507
  return sourcePaths.some((sourcePath) => {
478
- const source = toPosixPath(sourcePath).replace(/\/+$/, "");
479
- return relPath === source || relPath.startsWith(`${source}/`);
508
+ const source = normalizeSourcePrefix(sourcePath);
509
+ return source === "" || normalizedRelPath === source || normalizedRelPath.startsWith(`${source}/`);
480
510
  });
481
511
  }
482
512
 
@@ -627,6 +657,9 @@ function collectCandidateFiles(sourcePaths, mode) {
627
657
  }
628
658
 
629
659
  for (const sourcePath of sourcePaths) {
660
+ if (hasSkippedDirectorySegment(sourcePath)) {
661
+ continue;
662
+ }
630
663
  const absoluteSourcePath = path.resolve(REPO_ROOT, sourcePath);
631
664
  if (!fs.existsSync(absoluteSourcePath)) {
632
665
  continue;
@@ -198,11 +198,12 @@ try {
198
198
 
199
199
  node -e '
200
200
  const path = require("node:path");
201
- const { execSync } = require("node:child_process");
201
+ const { execFileSync, execSync } = require("node:child_process");
202
202
 
203
203
  const repoRoot = process.argv[1];
204
204
  const cacheDir = process.argv[2];
205
205
  const localVersionEnv = process.argv[3] || "";
206
+ const VERSION_LOOKUP_TIMEOUT_MS = Number(process.env.CORTEX_VERSION_LOOKUP_TIMEOUT_MS || 8000);
206
207
 
207
208
  function parseVersion(value) {
208
209
  const match = String(value || "").trim().match(/^v?(\d+)\.(\d+)\.(\d+)$/);
@@ -225,7 +226,7 @@ function getLocalVersion() {
225
226
  }
226
227
 
227
228
  try {
228
- const output = execSync("cortex --version", {
229
+ const output = execFileSync("cortex", ["--version"], {
229
230
  cwd: repoRoot,
230
231
  stdio: ["ignore", "pipe", "ignore"],
231
232
  encoding: "utf8",
@@ -282,11 +283,11 @@ try {
282
283
  const npmCache = path.join(cacheDir, "npm-cache");
283
284
  let latestRaw = "";
284
285
  try {
285
- latestRaw = execSync("npm view github:DanielBlomma/cortex version --json", {
286
+ latestRaw = execFileSync("npm", ["view", "github:DanielBlomma/cortex", "version", "--json"], {
286
287
  cwd: repoRoot,
287
288
  stdio: ["ignore", "pipe", "pipe"],
288
289
  encoding: "utf8",
289
- timeout: 2500,
290
+ timeout: VERSION_LOOKUP_TIMEOUT_MS,
290
291
  env: { ...process.env, NPM_CONFIG_CACHE: npmCache }
291
292
  }).trim();
292
293
  } catch (error) {
@@ -317,13 +318,19 @@ try {
317
318
  process.exit(0);
318
319
  }
319
320
 
320
- const hasUpdate = compareVersions(latestParsed, localParsed) > 0;
321
+ const comparison = compareVersions(latestParsed, localParsed);
321
322
  console.log(`[status] cortex_latest_version=${latestVersion}`);
322
323
 
323
- if (hasUpdate) {
324
+ if (comparison > 0) {
325
+ console.log("[status] cortex_version_state=update-available");
324
326
  console.log("[status] cortex_update_available=yes");
325
327
  console.log("[status] run: npm i -g github:DanielBlomma/cortex");
328
+ } else if (comparison < 0) {
329
+ console.log("[status] cortex_version_state=local-newer");
330
+ console.log("[status] cortex_update_available=no");
331
+ console.log("[status] note: local Cortex is newer than the published version");
326
332
  } else {
333
+ console.log("[status] cortex_version_state=current");
327
334
  console.log("[status] cortex_update_available=no");
328
335
  }
329
336
  } catch (error) {