@iderouter/index-mcp 0.2.0-beta.3 → 0.2.0-beta.5
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/package.json +1 -1
- package/src/index.js +112 -4
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -366,12 +366,13 @@ function contextProbeCacheKey(codebasePath) {
|
|
|
366
366
|
return `context:${codebasePath}`;
|
|
367
367
|
}
|
|
368
368
|
|
|
369
|
-
function summarizeContextText(text, maxLines =
|
|
369
|
+
function summarizeContextText(text, maxLines = 4) {
|
|
370
370
|
return String(text || "")
|
|
371
371
|
.split("\n")
|
|
372
372
|
.map((line) => line.trim())
|
|
373
373
|
.filter(Boolean)
|
|
374
374
|
.filter((line) => !/^#/.test(line))
|
|
375
|
+
.map((line) => line.replace(/\*\*/g, "").replace(/`/g, ""))
|
|
375
376
|
.slice(0, maxLines)
|
|
376
377
|
.join(" ");
|
|
377
378
|
}
|
|
@@ -6978,11 +6979,118 @@ function summarizeRepoTechStack(results) {
|
|
|
6978
6979
|
return stack;
|
|
6979
6980
|
}
|
|
6980
6981
|
|
|
6982
|
+
function summarizeRepoTechStackFromContext(contextProbe, fallbackStack) {
|
|
6983
|
+
const summary = String(contextProbe?.summary || "").toLowerCase();
|
|
6984
|
+
const merged = new Set(Array.isArray(fallbackStack) ? fallbackStack : []);
|
|
6985
|
+
if (summary.includes("go ")) merged.add("Go backend");
|
|
6986
|
+
if (summary.includes("react") || summary.includes("typescript")) merged.add("TypeScript/React frontend");
|
|
6987
|
+
if (summary.includes("tailwind")) merged.add("Tailwind CSS");
|
|
6988
|
+
if (summary.includes("gin")) merged.add("Gin web framework");
|
|
6989
|
+
if (summary.includes("gorm")) merged.add("GORM");
|
|
6990
|
+
if (summary.includes("redis")) merged.add("Redis");
|
|
6991
|
+
if (summary.includes("sqlite") || summary.includes("mysql") || summary.includes("postgresql")) {
|
|
6992
|
+
merged.add("Multi-database support");
|
|
6993
|
+
}
|
|
6994
|
+
return [...merged];
|
|
6995
|
+
}
|
|
6996
|
+
|
|
6997
|
+
function repoSummarySkeletonPaths(index) {
|
|
6998
|
+
const availableFiles = new Set(
|
|
6999
|
+
Array.isArray(index?.files)
|
|
7000
|
+
? index.files.map((file) => String(file?.relativePath || ""))
|
|
7001
|
+
: Array.isArray(index?.chunks)
|
|
7002
|
+
? index.chunks.map((chunk) => String(chunk?.relativePath || ""))
|
|
7003
|
+
: [],
|
|
7004
|
+
);
|
|
7005
|
+
const preferred = [
|
|
7006
|
+
"main.go",
|
|
7007
|
+
"router/main.go",
|
|
7008
|
+
"router/api-router.go",
|
|
7009
|
+
"router/web-router.go",
|
|
7010
|
+
"controller/relay.go",
|
|
7011
|
+
"controller/iderouter.go",
|
|
7012
|
+
"service/iderouter_routing.go",
|
|
7013
|
+
"service/channel_select.go",
|
|
7014
|
+
"service/iderouter_agent.go",
|
|
7015
|
+
"model/main.go",
|
|
7016
|
+
"model/channel.go",
|
|
7017
|
+
"relay/compatible_handler.go",
|
|
7018
|
+
"relay/common/relay_info.go",
|
|
7019
|
+
"setting/iderouter_setting/agent.go",
|
|
7020
|
+
"web/default/src/main.tsx",
|
|
7021
|
+
];
|
|
7022
|
+
return preferred.filter((relativePath) => availableFiles.has(relativePath));
|
|
7023
|
+
}
|
|
7024
|
+
|
|
7025
|
+
function summaryChunkScore(chunk) {
|
|
7026
|
+
const content = String(chunk?.content || "");
|
|
7027
|
+
let score = 0;
|
|
7028
|
+
if (chunk?.granularity !== "coarse") score += 3;
|
|
7029
|
+
if (/\bfunc\s+[A-Za-z0-9_]+/.test(content)) score += 5;
|
|
7030
|
+
if (/\btype\s+[A-Za-z0-9_]+/.test(content)) score += 3;
|
|
7031
|
+
if (/\bpackage\s+[A-Za-z0-9_]+/.test(content)) score += 1;
|
|
7032
|
+
if (/createRoot|ReactDOM|Gin|router|Handle|RunExpr|RelayInfo|Select/.test(content)) score += 2;
|
|
7033
|
+
return score;
|
|
7034
|
+
}
|
|
7035
|
+
|
|
7036
|
+
function selectSummaryChunkForFile(index, relativePath) {
|
|
7037
|
+
const chunks = Array.isArray(index?.chunks)
|
|
7038
|
+
? index.chunks.filter((chunk) => String(chunk.relativePath || "") === relativePath)
|
|
7039
|
+
: [];
|
|
7040
|
+
if (chunks.length === 0) return null;
|
|
7041
|
+
return chunks
|
|
7042
|
+
.slice()
|
|
7043
|
+
.sort((left, right) => summaryChunkScore(right) - summaryChunkScore(left) || Number(left.startLine || 0) - Number(right.startLine || 0))[0];
|
|
7044
|
+
}
|
|
7045
|
+
|
|
7046
|
+
function summarizeEntrypoints(index, results, limit = 5) {
|
|
7047
|
+
const preferredRoleOrder = ["controller", "router", "service", "relay", "model", "pkg", "frontend", "core"];
|
|
7048
|
+
const byPath = new Map((results || []).map((result) => [String(result.relativePath || ""), result]));
|
|
7049
|
+
const skeleton = [];
|
|
7050
|
+
for (const relativePath of repoSummarySkeletonPaths(index)) {
|
|
7051
|
+
const item = byPath.get(relativePath) || selectSummaryChunkForFile(index, relativePath);
|
|
7052
|
+
if (item) skeleton.push(item);
|
|
7053
|
+
if (skeleton.length >= limit) return skeleton.slice(0, limit);
|
|
7054
|
+
}
|
|
7055
|
+
const bestByRole = new Map();
|
|
7056
|
+
for (const result of results || []) {
|
|
7057
|
+
const role = pathRole(result.relativePath);
|
|
7058
|
+
if (!preferredRoleOrder.includes(role)) continue;
|
|
7059
|
+
const existing = bestByRole.get(role);
|
|
7060
|
+
if (!existing || Number(result.score || 0) > Number(existing.score || 0)) {
|
|
7061
|
+
bestByRole.set(role, result);
|
|
7062
|
+
}
|
|
7063
|
+
}
|
|
7064
|
+
const ordered = [];
|
|
7065
|
+
const seenFile = new Set(skeleton.map((item) => item.relativePath));
|
|
7066
|
+
for (const item of skeleton) {
|
|
7067
|
+
ordered.push(item);
|
|
7068
|
+
}
|
|
7069
|
+
for (const role of preferredRoleOrder) {
|
|
7070
|
+
const item = bestByRole.get(role);
|
|
7071
|
+
if (item && seenFile.has(item.relativePath)) continue;
|
|
7072
|
+
if (item) ordered.push(item);
|
|
7073
|
+
if (ordered.length >= limit) break;
|
|
7074
|
+
}
|
|
7075
|
+
if (ordered.length >= limit) return ordered.slice(0, limit);
|
|
7076
|
+
const seen = new Set(ordered.map((item) => `${item.relativePath}:${item.startLine}:${item.endLine}`));
|
|
7077
|
+
for (const result of results || []) {
|
|
7078
|
+
const key = `${result.relativePath}:${result.startLine}:${result.endLine}`;
|
|
7079
|
+
if (seen.has(key)) continue;
|
|
7080
|
+
if (["docs", "tests", "mcp", "other"].includes(pathRole(result.relativePath))) continue;
|
|
7081
|
+
ordered.push(result);
|
|
7082
|
+
seen.add(key);
|
|
7083
|
+
if (ordered.length >= limit) break;
|
|
7084
|
+
}
|
|
7085
|
+
return ordered;
|
|
7086
|
+
}
|
|
7087
|
+
|
|
6981
7088
|
function repoSummaryLines(codebasePath, state, contextProbe) {
|
|
6982
7089
|
const results = Array.isArray(state?.results) ? state.results : [];
|
|
6983
7090
|
const topResults = results.slice(0, 8);
|
|
6984
7091
|
const domains = summarizeRepoDomains(topResults);
|
|
6985
|
-
const stack = summarizeRepoTechStack(topResults);
|
|
7092
|
+
const stack = summarizeRepoTechStackFromContext(contextProbe, summarizeRepoTechStack(topResults));
|
|
7093
|
+
const entrypoints = summarizeEntrypoints(state?.index, topResults, 5);
|
|
6986
7094
|
const lines = [
|
|
6987
7095
|
`Fast repository summary for ${codebasePath}:`,
|
|
6988
7096
|
"",
|
|
@@ -7001,10 +7109,10 @@ function repoSummaryLines(codebasePath, state, contextProbe) {
|
|
|
7001
7109
|
lines.push(`- ${path.basename(item.filePath)}: ${item.excerpt || "context file detected"}`);
|
|
7002
7110
|
}
|
|
7003
7111
|
}
|
|
7004
|
-
if (
|
|
7112
|
+
if (entrypoints.length > 0) {
|
|
7005
7113
|
lines.push("");
|
|
7006
7114
|
lines.push("Key entrypoints:");
|
|
7007
|
-
for (const result of
|
|
7115
|
+
for (const result of entrypoints) {
|
|
7008
7116
|
lines.push(`- ${result.relativePath}:${result.startLine}-${result.endLine}`);
|
|
7009
7117
|
}
|
|
7010
7118
|
}
|