@liendev/lien 0.28.1 → 0.29.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.
- package/dist/index.js +126 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -8745,6 +8745,91 @@ function wrapToolHandler(schema, handler) {
|
|
|
8745
8745
|
};
|
|
8746
8746
|
}
|
|
8747
8747
|
|
|
8748
|
+
// src/mcp/utils/metadata-shaper.ts
|
|
8749
|
+
var FIELD_ALLOWLISTS = {
|
|
8750
|
+
semantic_search: /* @__PURE__ */ new Set([
|
|
8751
|
+
"language",
|
|
8752
|
+
"type",
|
|
8753
|
+
"symbolName",
|
|
8754
|
+
"symbolType",
|
|
8755
|
+
"signature",
|
|
8756
|
+
"parentClass",
|
|
8757
|
+
"parameters",
|
|
8758
|
+
"exports",
|
|
8759
|
+
"repoId"
|
|
8760
|
+
]),
|
|
8761
|
+
find_similar: /* @__PURE__ */ new Set([
|
|
8762
|
+
"language",
|
|
8763
|
+
"type",
|
|
8764
|
+
"symbolName",
|
|
8765
|
+
"symbolType",
|
|
8766
|
+
"signature",
|
|
8767
|
+
"parentClass",
|
|
8768
|
+
"parameters",
|
|
8769
|
+
"exports"
|
|
8770
|
+
]),
|
|
8771
|
+
get_files_context: /* @__PURE__ */ new Set([
|
|
8772
|
+
"language",
|
|
8773
|
+
"type",
|
|
8774
|
+
"symbolName",
|
|
8775
|
+
"symbolType",
|
|
8776
|
+
"signature",
|
|
8777
|
+
"parentClass",
|
|
8778
|
+
"parameters",
|
|
8779
|
+
"exports",
|
|
8780
|
+
"imports",
|
|
8781
|
+
"importedSymbols",
|
|
8782
|
+
"callSites",
|
|
8783
|
+
"symbols"
|
|
8784
|
+
]),
|
|
8785
|
+
list_functions: /* @__PURE__ */ new Set([
|
|
8786
|
+
"language",
|
|
8787
|
+
"type",
|
|
8788
|
+
"symbolName",
|
|
8789
|
+
"symbolType",
|
|
8790
|
+
"signature",
|
|
8791
|
+
"parentClass",
|
|
8792
|
+
"parameters",
|
|
8793
|
+
"exports",
|
|
8794
|
+
"symbols"
|
|
8795
|
+
])
|
|
8796
|
+
};
|
|
8797
|
+
function deduplicateResults(results) {
|
|
8798
|
+
const seen = /* @__PURE__ */ new Set();
|
|
8799
|
+
return results.filter((r) => {
|
|
8800
|
+
const key = JSON.stringify([r.metadata.repoId ?? "", r.metadata.file, r.metadata.startLine, r.metadata.endLine]);
|
|
8801
|
+
if (seen.has(key)) return false;
|
|
8802
|
+
seen.add(key);
|
|
8803
|
+
return true;
|
|
8804
|
+
});
|
|
8805
|
+
}
|
|
8806
|
+
function pickMetadata(metadata, allowlist) {
|
|
8807
|
+
const result = {
|
|
8808
|
+
file: metadata.file,
|
|
8809
|
+
startLine: metadata.startLine,
|
|
8810
|
+
endLine: metadata.endLine
|
|
8811
|
+
};
|
|
8812
|
+
const out = result;
|
|
8813
|
+
for (const key of allowlist) {
|
|
8814
|
+
if (key === "file" || key === "startLine" || key === "endLine") continue;
|
|
8815
|
+
if (metadata[key] !== void 0) {
|
|
8816
|
+
out[key] = metadata[key];
|
|
8817
|
+
}
|
|
8818
|
+
}
|
|
8819
|
+
return result;
|
|
8820
|
+
}
|
|
8821
|
+
function shapeResultMetadata(result, tool) {
|
|
8822
|
+
return {
|
|
8823
|
+
content: result.content,
|
|
8824
|
+
metadata: pickMetadata(result.metadata, FIELD_ALLOWLISTS[tool]),
|
|
8825
|
+
score: result.score,
|
|
8826
|
+
relevance: result.relevance
|
|
8827
|
+
};
|
|
8828
|
+
}
|
|
8829
|
+
function shapeResults(results, tool) {
|
|
8830
|
+
return results.map((r) => shapeResultMetadata(r, tool));
|
|
8831
|
+
}
|
|
8832
|
+
|
|
8748
8833
|
// src/mcp/handlers/semantic-search.ts
|
|
8749
8834
|
import { QdrantDB } from "@liendev/core";
|
|
8750
8835
|
function groupResultsByRepo(results) {
|
|
@@ -8780,15 +8865,31 @@ async function handleSemanticSearch(args, ctx) {
|
|
|
8780
8865
|
results = await vectorDB.search(queryEmbedding, limit, query);
|
|
8781
8866
|
log(`Found ${results.length} results`);
|
|
8782
8867
|
}
|
|
8868
|
+
results = deduplicateResults(results);
|
|
8869
|
+
const notes = [];
|
|
8870
|
+
if (crossRepoFallback) {
|
|
8871
|
+
notes.push("Cross-repo search requires Qdrant backend. Fell back to single-repo search.");
|
|
8872
|
+
}
|
|
8873
|
+
if (results.length > 0 && results.every((r) => r.relevance === "not_relevant")) {
|
|
8874
|
+
notes.push("No relevant matches found.");
|
|
8875
|
+
log("Returning 0 results (all not_relevant)");
|
|
8876
|
+
return {
|
|
8877
|
+
indexInfo: getIndexMetadata(),
|
|
8878
|
+
results: [],
|
|
8879
|
+
note: notes.join(" ")
|
|
8880
|
+
};
|
|
8881
|
+
}
|
|
8882
|
+
log(`Returning ${results.length} results`);
|
|
8883
|
+
const shaped = shapeResults(results, "semantic_search");
|
|
8783
8884
|
const response = {
|
|
8784
8885
|
indexInfo: getIndexMetadata(),
|
|
8785
|
-
results
|
|
8886
|
+
results: shaped
|
|
8786
8887
|
};
|
|
8787
8888
|
if (crossRepo && vectorDB instanceof QdrantDB) {
|
|
8788
|
-
response.groupedByRepo = groupResultsByRepo(
|
|
8889
|
+
response.groupedByRepo = groupResultsByRepo(shaped);
|
|
8789
8890
|
}
|
|
8790
|
-
if (
|
|
8791
|
-
response.note = "
|
|
8891
|
+
if (notes.length > 0) {
|
|
8892
|
+
response.note = notes.join(" ");
|
|
8792
8893
|
}
|
|
8793
8894
|
return response;
|
|
8794
8895
|
}
|
|
@@ -8820,6 +8921,12 @@ async function handleFindSimilar(args, ctx) {
|
|
|
8820
8921
|
const limit = validatedArgs.limit ?? 5;
|
|
8821
8922
|
const extraLimit = limit + 10;
|
|
8822
8923
|
let results = await vectorDB.search(codeEmbedding, extraLimit, validatedArgs.code);
|
|
8924
|
+
results = deduplicateResults(results);
|
|
8925
|
+
const inputCode = validatedArgs.code.trim();
|
|
8926
|
+
results = results.filter((r) => {
|
|
8927
|
+
if (r.score >= 0.1) return true;
|
|
8928
|
+
return r.content.trim() !== inputCode;
|
|
8929
|
+
});
|
|
8823
8930
|
const filtersApplied = { prunedLowRelevance: 0 };
|
|
8824
8931
|
if (validatedArgs.language) {
|
|
8825
8932
|
filtersApplied.language = validatedArgs.language;
|
|
@@ -8836,7 +8943,7 @@ async function handleFindSimilar(args, ctx) {
|
|
|
8836
8943
|
const hasFilters = filtersApplied.language || filtersApplied.pathHint || filtersApplied.prunedLowRelevance > 0;
|
|
8837
8944
|
return {
|
|
8838
8945
|
indexInfo: getIndexMetadata(),
|
|
8839
|
-
results: finalResults,
|
|
8946
|
+
results: shapeResults(finalResults, "find_similar"),
|
|
8840
8947
|
...hasFilters && { filtersApplied }
|
|
8841
8948
|
};
|
|
8842
8949
|
}
|
|
@@ -9044,18 +9151,26 @@ function buildScanLimitNote(hitScanLimit) {
|
|
|
9044
9151
|
return hitScanLimit ? "Scanned 10,000 chunks (limit reached). Test associations may be incomplete for large codebases." : void 0;
|
|
9045
9152
|
}
|
|
9046
9153
|
function buildSingleFileResponse(filepath, filesData, indexInfo, note) {
|
|
9154
|
+
const data = filesData[filepath];
|
|
9047
9155
|
return {
|
|
9048
9156
|
indexInfo,
|
|
9049
9157
|
file: filepath,
|
|
9050
|
-
chunks:
|
|
9051
|
-
testAssociations:
|
|
9158
|
+
chunks: shapeResults(data.chunks, "get_files_context"),
|
|
9159
|
+
testAssociations: data.testAssociations,
|
|
9052
9160
|
...note && { note }
|
|
9053
9161
|
};
|
|
9054
9162
|
}
|
|
9055
9163
|
function buildMultiFileResponse(filesData, indexInfo, note) {
|
|
9164
|
+
const shaped = {};
|
|
9165
|
+
for (const [filepath, data] of Object.entries(filesData)) {
|
|
9166
|
+
shaped[filepath] = {
|
|
9167
|
+
chunks: shapeResults(data.chunks, "get_files_context"),
|
|
9168
|
+
testAssociations: data.testAssociations
|
|
9169
|
+
};
|
|
9170
|
+
}
|
|
9056
9171
|
return {
|
|
9057
9172
|
indexInfo,
|
|
9058
|
-
files:
|
|
9173
|
+
files: shaped,
|
|
9059
9174
|
...note && { note }
|
|
9060
9175
|
};
|
|
9061
9176
|
}
|
|
@@ -9160,11 +9275,12 @@ async function handleListFunctions(args, ctx) {
|
|
|
9160
9275
|
log(`Symbol query failed: ${error}`);
|
|
9161
9276
|
queryResult = await performContentScan(vectorDB, validatedArgs, log);
|
|
9162
9277
|
}
|
|
9163
|
-
|
|
9278
|
+
const dedupedResults = deduplicateResults(queryResult.results);
|
|
9279
|
+
log(`Found ${dedupedResults.length} matches using ${queryResult.method} method`);
|
|
9164
9280
|
return {
|
|
9165
9281
|
indexInfo: getIndexMetadata(),
|
|
9166
9282
|
method: queryResult.method,
|
|
9167
|
-
results:
|
|
9283
|
+
results: shapeResults(dedupedResults, "list_functions"),
|
|
9168
9284
|
note: queryResult.method === "content" ? 'Using content search. Run "lien reindex" to enable faster symbol-based queries.' : void 0
|
|
9169
9285
|
};
|
|
9170
9286
|
}
|