openkrak-mcp 1.0.17 → 1.0.18
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/index.js +89 -9
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -242516,10 +242516,11 @@ function detectSecurityPatterns(filePath, content) {
|
|
|
242516
242516
|
}
|
|
242517
242517
|
async function classifyTopology(repoRoot, allFiles) {
|
|
242518
242518
|
const type = await detectProjectType(repoRoot);
|
|
242519
|
+
const framework = await detectFramework(repoRoot);
|
|
242519
242520
|
const entryPoints = detectEntryPoints(allFiles);
|
|
242520
242521
|
const layers = detectLayers(allFiles);
|
|
242521
242522
|
const modules = detectModules(allFiles);
|
|
242522
|
-
return { type, entry_points: entryPoints, layers, modules };
|
|
242523
|
+
return { type, entry_points: entryPoints, layers, modules, framework };
|
|
242523
242524
|
}
|
|
242524
242525
|
async function detectProjectType(repoRoot) {
|
|
242525
242526
|
try {
|
|
@@ -242529,7 +242530,7 @@ async function detectProjectType(repoRoot) {
|
|
|
242529
242530
|
if (pkg.private === true && Array.isArray(pkg.workspaces)) return "monorepo";
|
|
242530
242531
|
} catch {
|
|
242531
242532
|
}
|
|
242532
|
-
for (const config of ["nx.json", "lerna.json"]) {
|
|
242533
|
+
for (const config of ["nx.json", "lerna.json", "pnpm-workspace.yaml", "turbo.json"]) {
|
|
242533
242534
|
try {
|
|
242534
242535
|
await import_promises3.default.access(import_path4.default.join(repoRoot, config));
|
|
242535
242536
|
return "monorepo";
|
|
@@ -242538,12 +242539,70 @@ async function detectProjectType(repoRoot) {
|
|
|
242538
242539
|
}
|
|
242539
242540
|
return "monolith";
|
|
242540
242541
|
}
|
|
242542
|
+
async function detectFramework(repoRoot) {
|
|
242543
|
+
try {
|
|
242544
|
+
const pkgPath = import_path4.default.join(repoRoot, "package.json");
|
|
242545
|
+
const pkg = JSON.parse(await import_promises3.default.readFile(pkgPath, "utf-8"));
|
|
242546
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
242547
|
+
if (deps["next"]) return `next@${deps["next"].replace(/[\^~]/g, "")}`;
|
|
242548
|
+
if (deps["nuxt"]) return `nuxt@${deps["nuxt"].replace(/[\^~]/g, "")}`;
|
|
242549
|
+
if (deps["@remix-run/react"]) return "remix";
|
|
242550
|
+
if (deps["astro"]) return `astro@${deps["astro"].replace(/[\^~]/g, "")}`;
|
|
242551
|
+
if (deps["svelte"]) return "svelte";
|
|
242552
|
+
if (deps["vue"]) return `vue@${deps["vue"].replace(/[\^~]/g, "")}`;
|
|
242553
|
+
if (deps["react"]) return `react@${deps["react"].replace(/[\^~]/g, "")}`;
|
|
242554
|
+
if (deps["express"]) return `express@${deps["express"].replace(/[\^~]/g, "")}`;
|
|
242555
|
+
if (deps["fastify"]) return `fastify@${deps["fastify"].replace(/[\^~]/g, "")}`;
|
|
242556
|
+
if (deps["hono"]) return `hono@${deps["hono"].replace(/[\^~]/g, "")}`;
|
|
242557
|
+
if (deps["@nestjs/core"]) return "nestjs";
|
|
242558
|
+
if (deps["@angular/core"]) return "angular";
|
|
242559
|
+
} catch {
|
|
242560
|
+
}
|
|
242561
|
+
try {
|
|
242562
|
+
await import_promises3.default.access(import_path4.default.join(repoRoot, "next.config.js"));
|
|
242563
|
+
return "next";
|
|
242564
|
+
} catch {
|
|
242565
|
+
}
|
|
242566
|
+
try {
|
|
242567
|
+
await import_promises3.default.access(import_path4.default.join(repoRoot, "next.config.mjs"));
|
|
242568
|
+
return "next";
|
|
242569
|
+
} catch {
|
|
242570
|
+
}
|
|
242571
|
+
try {
|
|
242572
|
+
await import_promises3.default.access(import_path4.default.join(repoRoot, "next.config.ts"));
|
|
242573
|
+
return "next";
|
|
242574
|
+
} catch {
|
|
242575
|
+
}
|
|
242576
|
+
try {
|
|
242577
|
+
await import_promises3.default.access(import_path4.default.join(repoRoot, "vite.config.ts"));
|
|
242578
|
+
return "vite";
|
|
242579
|
+
} catch {
|
|
242580
|
+
}
|
|
242581
|
+
try {
|
|
242582
|
+
await import_promises3.default.access(import_path4.default.join(repoRoot, "astro.config.mjs"));
|
|
242583
|
+
return "astro";
|
|
242584
|
+
} catch {
|
|
242585
|
+
}
|
|
242586
|
+
return null;
|
|
242587
|
+
}
|
|
242541
242588
|
function detectEntryPoints(files) {
|
|
242542
242589
|
const entries = [];
|
|
242543
242590
|
for (const f of files) {
|
|
242544
|
-
if (/\/(index|main|
|
|
242545
|
-
const type = f.includes("cli") ? "cli" : f.includes("server")
|
|
242591
|
+
if (/\/(index|main|server|cli)\.(ts|js)x?$/.test(f)) {
|
|
242592
|
+
const type = f.includes("cli") ? "cli" : f.includes("server") ? "api" : "main";
|
|
242546
242593
|
entries.push({ path: f, type });
|
|
242594
|
+
continue;
|
|
242595
|
+
}
|
|
242596
|
+
if (/^app\/.*page\.(ts|js)x?$/.test(f) || /^app\/layout\.(ts|js)x?$/.test(f)) {
|
|
242597
|
+
entries.push({ path: f, type: "api" });
|
|
242598
|
+
continue;
|
|
242599
|
+
}
|
|
242600
|
+
if (/^app\/.*route\.(ts|js)x?$/.test(f) || /^pages\/api\//.test(f)) {
|
|
242601
|
+
entries.push({ path: f, type: "api" });
|
|
242602
|
+
continue;
|
|
242603
|
+
}
|
|
242604
|
+
if (/^src\/(main|index|App)\.(ts|js)x?$/.test(f)) {
|
|
242605
|
+
entries.push({ path: f, type: "main" });
|
|
242547
242606
|
}
|
|
242548
242607
|
}
|
|
242549
242608
|
return entries;
|
|
@@ -243339,6 +243398,7 @@ function detectGodObjects(graph, couplingScores, fileRole) {
|
|
|
243339
243398
|
for (const [file, count] of nodeCountByFile) {
|
|
243340
243399
|
if (count <= NODE_COUNT_THRESHOLD) continue;
|
|
243341
243400
|
if (fileRole.get(file) === "test") continue;
|
|
243401
|
+
if (file.endsWith("/index.ts") || file.endsWith("/index.js") || file === "index.ts") continue;
|
|
243342
243402
|
const coupling = couplingScores.get(file);
|
|
243343
243403
|
if (!coupling) continue;
|
|
243344
243404
|
if (coupling.fan_in <= FAN_IN_THRESHOLD && coupling.fan_out <= FAN_OUT_THRESHOLD) continue;
|
|
@@ -243366,7 +243426,8 @@ function aggregateHotspots(params) {
|
|
|
243366
243426
|
cycleFindings,
|
|
243367
243427
|
affectedSymbolsByFile,
|
|
243368
243428
|
cyclePaths = [],
|
|
243369
|
-
graph
|
|
243429
|
+
graph,
|
|
243430
|
+
changeFrequencyMap = /* @__PURE__ */ new Map()
|
|
243370
243431
|
} = params;
|
|
243371
243432
|
const cycleFilesFromPaths = /* @__PURE__ */ new Map();
|
|
243372
243433
|
for (const path7 of cyclePaths) {
|
|
@@ -243418,7 +243479,10 @@ function aggregateHotspots(params) {
|
|
|
243418
243479
|
const isRepository = file.includes("/repositories/") || file.includes("/repository/") || file.toLowerCase().includes("repository");
|
|
243419
243480
|
const isFoundational = isRepository && methodCount >= 3 && (coupling?.fan_in ?? 0) >= 1;
|
|
243420
243481
|
const foundationalBonus = isFoundational ? 0.25 : 0;
|
|
243421
|
-
const
|
|
243482
|
+
const changeFreq = changeFrequencyMap.get(file) ?? 0;
|
|
243483
|
+
const maxChangeFreq = Math.max(1, ...[...changeFrequencyMap.values()]);
|
|
243484
|
+
const changeFreqScore = Math.min(1, changeFreq / maxChangeFreq);
|
|
243485
|
+
const rawScore = couplingScore * 0.35 + complexityScore * 0.15 + methodScore * 0.1 + changeFreqScore * 0.1 + violationPenalty + godObjectBonus + cyclePenalty + foundationalBonus;
|
|
243422
243486
|
const finalScore = Math.min(1, rawScore);
|
|
243423
243487
|
const reasons = [];
|
|
243424
243488
|
if (coupling && couplingScore > 0) {
|
|
@@ -243555,10 +243619,11 @@ function buildArchitectureViolationFindings(violations) {
|
|
|
243555
243619
|
}));
|
|
243556
243620
|
}
|
|
243557
243621
|
var logger3 = createLogger("hotspot_registry");
|
|
243558
|
-
async function runHotspotRegistry(store) {
|
|
243622
|
+
async function runHotspotRegistry(store, opts) {
|
|
243559
243623
|
const start = Date.now();
|
|
243560
243624
|
const errors = [];
|
|
243561
243625
|
const scanId = store.getMeta().scan_id;
|
|
243626
|
+
const changeFrequencyMap = opts?.changeFrequencyMap ?? /* @__PURE__ */ new Map();
|
|
243562
243627
|
const log = logger3.child({ scan_id: scanId });
|
|
243563
243628
|
log.info({ event: "hotspot_registry.start" }, "Hotspot Registry started");
|
|
243564
243629
|
const graph = store.getDependencyGraph();
|
|
@@ -243610,7 +243675,8 @@ async function runHotspotRegistry(store) {
|
|
|
243610
243675
|
cycleFindings,
|
|
243611
243676
|
affectedSymbolsByFile,
|
|
243612
243677
|
cyclePaths: graph.stats.cycle_paths ?? [],
|
|
243613
|
-
graph
|
|
243678
|
+
graph,
|
|
243679
|
+
changeFrequencyMap
|
|
243614
243680
|
});
|
|
243615
243681
|
const couplingFindings = buildCouplingFindings(couplingScores.values(), graph.nodes);
|
|
243616
243682
|
const complexityFindings = buildComplexityFindings(complexityScores);
|
|
@@ -244856,8 +244922,22 @@ async function runPipeline(options) {
|
|
|
244856
244922
|
try {
|
|
244857
244923
|
logger7.info("Step 1/6: DeepStrike");
|
|
244858
244924
|
await runDeepStrike(store, { repoRoot: options.repoPath });
|
|
244925
|
+
const changeFrequencyMap = /* @__PURE__ */ new Map();
|
|
244926
|
+
try {
|
|
244927
|
+
const { execSync } = await import("child_process");
|
|
244928
|
+
const gitLog = execSync("git log --name-only --pretty=format: -- .", {
|
|
244929
|
+
cwd: options.repoPath,
|
|
244930
|
+
encoding: "utf-8",
|
|
244931
|
+
timeout: 8e3
|
|
244932
|
+
});
|
|
244933
|
+
for (const line of gitLog.split("\n")) {
|
|
244934
|
+
const trimmed = line.trim().replace(/\\/g, "/");
|
|
244935
|
+
if (trimmed) changeFrequencyMap.set(trimmed, (changeFrequencyMap.get(trimmed) ?? 0) + 1);
|
|
244936
|
+
}
|
|
244937
|
+
} catch {
|
|
244938
|
+
}
|
|
244859
244939
|
logger7.info("Step 2/6: Hotspot Registry");
|
|
244860
|
-
await runHotspotRegistry(store);
|
|
244940
|
+
await runHotspotRegistry(store, { repoRoot: options.repoPath, changeFrequencyMap });
|
|
244861
244941
|
logger7.info("Step 3/6: Correlation Engine");
|
|
244862
244942
|
await runCorrelationEngine(store);
|
|
244863
244943
|
logger7.info("Step 4/6: Blast Radius Engine");
|