ultracode 5.4.0 → 5.6.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/chunks/analysis-tool-handlers-GH5FDEWW.js +817 -0
- package/dist/chunks/analysis-tool-handlers-IXP4MWZX.js +817 -0
- package/dist/chunks/analysis-tool-handlers-LC2BTQYK.js +13 -0
- package/dist/chunks/analysis-tool-handlers-QYFKQPFL.js +817 -0
- package/dist/chunks/autodoc-tool-handlers-2HF6ERYN.js +1112 -0
- package/dist/chunks/autodoc-tool-handlers-4OGQJ7C3.js +1112 -0
- package/dist/chunks/autodoc-tool-handlers-N736CB56.js +138 -0
- package/dist/chunks/autodoc-tool-handlers-NQYBY6U4.js +1112 -0
- package/dist/chunks/branch-tool-handlers-KW3H4FJK.js +276 -0
- package/dist/chunks/branch-tool-handlers-QOUDZKJ2.js +276 -0
- package/dist/chunks/branch-tool-handlers-RB2U36KI.js +2 -0
- package/dist/chunks/branch-tool-handlers-ZHJM6PDK.js +276 -0
- package/dist/chunks/chunk-2Z6OQPYC.js +656 -0
- package/dist/chunks/chunk-3MQ7LRPN.js +322 -0
- package/dist/chunks/chunk-4W6QYGXZ.js +10 -0
- package/dist/chunks/chunk-533NFGUG.js +1 -0
- package/dist/chunks/chunk-5NUPOPWM.js +1 -0
- package/dist/chunks/chunk-AK4HIPA2.js +322 -0
- package/dist/chunks/chunk-B3H5NS3I.js +656 -0
- package/dist/chunks/chunk-DPTZHDST.js +4 -0
- package/dist/chunks/chunk-E5HQWLU5.js +322 -0
- package/dist/chunks/chunk-EOH25B5P.js +572 -0
- package/dist/chunks/chunk-ESV6F6E3.js +3179 -0
- package/dist/chunks/chunk-FPELPFER.js +924 -0
- package/dist/chunks/chunk-G6J42I55.js +161 -0
- package/dist/chunks/chunk-GCQE7ZYW.js +1 -0
- package/dist/chunks/chunk-GTIF6MOX.js +1 -0
- package/dist/chunks/chunk-I6STSSAK.js +2 -0
- package/dist/chunks/chunk-J2WBGTK2.js +4697 -0
- package/dist/chunks/chunk-KAYOX5EB.js +4697 -0
- package/dist/chunks/chunk-KPMTACOT.js +656 -0
- package/dist/chunks/chunk-L376GZ44.js +3179 -0
- package/dist/chunks/chunk-LCTOTHDA.js +15 -0
- package/dist/chunks/chunk-LEDJ7GVQ.js +316 -0
- package/dist/chunks/chunk-LH4OUKNZ.js +277 -0
- package/dist/chunks/chunk-O6IE2MEZ.js +161 -0
- package/dist/chunks/chunk-OEXPCY3F.js +316 -0
- package/dist/chunks/chunk-OMXOLFDN.js +924 -0
- package/dist/chunks/chunk-PLPBXWOU.js +3179 -0
- package/dist/chunks/chunk-PWLE5DN2.js +572 -0
- package/dist/chunks/chunk-PY43JPWL.js +447 -0
- package/dist/chunks/chunk-Q3B4EB7A.js +15 -0
- package/dist/chunks/chunk-Q5LPVLXA.js +337 -0
- package/dist/chunks/chunk-QIRZHZK2.js +5 -0
- package/dist/chunks/chunk-ROQ27LSL.js +924 -0
- package/dist/chunks/chunk-S5Q7BD6J.js +572 -0
- package/dist/chunks/chunk-SAMX3HJQ.js +337 -0
- package/dist/chunks/chunk-SV3WKUNV.js +1 -0
- package/dist/chunks/chunk-TCHCDCDO.js +167 -0
- package/dist/chunks/chunk-TR3HS7U6.js +316 -0
- package/dist/chunks/chunk-TUWE6FCW.js +167 -0
- package/dist/chunks/chunk-TVOTA7EE.js +277 -0
- package/dist/chunks/chunk-VS44D772.js +337 -0
- package/dist/chunks/chunk-WIE3G5ES.js +167 -0
- package/dist/chunks/chunk-XG3ACLWR.js +5 -0
- package/dist/chunks/chunk-XJ2Z5QQO.js +1 -0
- package/dist/chunks/chunk-XK2NY7RB.js +277 -0
- package/dist/chunks/chunk-Y4F7NZFZ.js +4700 -0
- package/dist/chunks/chunk-YS75L3ZS.js +161 -0
- package/dist/chunks/chunk-ZVG5HHI3.js +15 -0
- package/dist/chunks/dev-agent-DDDIVWOF.js +1 -0
- package/dist/chunks/dev-agent-E2VCFKXN.js +1624 -0
- package/dist/chunks/dev-agent-KJNSU5KQ.js +1624 -0
- package/dist/chunks/dev-agent-NDERYIPV.js +1624 -0
- package/dist/chunks/faiss-provider-7R4BQDIV.js +12 -0
- package/dist/chunks/faiss-provider-7ZFRSDN5.js +12 -0
- package/dist/chunks/faiss-provider-SXB7FTLB.js +1 -0
- package/dist/chunks/faiss-provider-TKLBEUSH.js +12 -0
- package/dist/chunks/file-tool-handlers-5DODQXGF.js +1027 -0
- package/dist/chunks/file-tool-handlers-KGHLE4KR.js +1027 -0
- package/dist/chunks/file-tool-handlers-KTOQ4NFS.js +12 -0
- package/dist/chunks/file-tool-handlers-V4SFUDQB.js +1027 -0
- package/dist/chunks/graph-metrics-tool-handlers-3AV4X4ZY.js +65 -0
- package/dist/chunks/graph-metrics-tool-handlers-3VMDQHJ6.js +65 -0
- package/dist/chunks/graph-metrics-tool-handlers-BZ6E6YHF.js +1 -0
- package/dist/chunks/graph-metrics-tool-handlers-IYBGSXL7.js +65 -0
- package/dist/chunks/graph-storage-factory-2CQ2RPDV.js +13 -0
- package/dist/chunks/graph-storage-factory-C5SMMYL6.js +13 -0
- package/dist/chunks/graph-storage-factory-EEO2V3GJ.js +1 -0
- package/dist/chunks/graph-storage-factory-WBCTXP34.js +13 -0
- package/dist/chunks/history-tool-handlers-AS7OQFZI.js +1 -0
- package/dist/chunks/history-tool-handlers-FSNJYXV2.js +208 -0
- package/dist/chunks/history-tool-handlers-JZAH4EIQ.js +208 -0
- package/dist/chunks/history-tool-handlers-KCSCXZ7T.js +208 -0
- package/dist/chunks/incremental-updater-A2EL4QXU.js +14 -0
- package/dist/chunks/incremental-updater-EQIKBVY2.js +14 -0
- package/dist/chunks/incremental-updater-JFGRPH3B.js +14 -0
- package/dist/chunks/incremental-updater-S5BAAGHP.js +1 -0
- package/dist/chunks/indexer-agent-ASKY7JPG.js +1 -0
- package/dist/chunks/indexer-agent-NKAOF323.js +21 -0
- package/dist/chunks/indexer-agent-PJN5IOKQ.js +21 -0
- package/dist/chunks/indexer-agent-WRJFWKZX.js +21 -0
- package/dist/chunks/indexing-pipeline-D4P2O72Z.js +249 -0
- package/dist/chunks/indexing-pipeline-L7C543N4.js +1 -0
- package/dist/chunks/indexing-pipeline-NHPRN3AB.js +249 -0
- package/dist/chunks/indexing-pipeline-ZAXCZU22.js +249 -0
- package/dist/chunks/layered-faiss-provider-62CNW54X.js +1 -0
- package/dist/chunks/layered-faiss-provider-O7L77GFX.js +12 -0
- package/dist/chunks/layered-faiss-provider-RVHLHLPK.js +12 -0
- package/dist/chunks/layered-faiss-provider-YT7EDIJI.js +12 -0
- package/dist/chunks/merge-agent-3RF7VFF5.js +2481 -0
- package/dist/chunks/merge-agent-JCKTCBCE.js +2481 -0
- package/dist/chunks/merge-agent-VCL7OXPN.js +2481 -0
- package/dist/chunks/merge-agent-ZGK24WVF.js +11 -0
- package/dist/chunks/merge-tool-handlers-GV2LOIKU.js +277 -0
- package/dist/chunks/merge-tool-handlers-TYDWU5X2.js +277 -0
- package/dist/chunks/merge-tool-handlers-U7X2ZO2M.js +1 -0
- package/dist/chunks/merge-tool-handlers-YH62ZLPJ.js +277 -0
- package/dist/chunks/pattern-tool-handlers-76NF5JDS.js +13 -0
- package/dist/chunks/pattern-tool-handlers-IJAGEIVD.js +1549 -0
- package/dist/chunks/pattern-tool-handlers-VA5WYA62.js +1549 -0
- package/dist/chunks/pattern-tool-handlers-WQ6UBMJS.js +1549 -0
- package/dist/chunks/query-agent-36ADGCFZ.js +1 -0
- package/dist/chunks/query-agent-H22CR5N5.js +191 -0
- package/dist/chunks/query-agent-K2UGZS4M.js +191 -0
- package/dist/chunks/query-agent-YJCEHOXD.js +191 -0
- package/dist/chunks/semantic-agent-AC7CBEDE.js +6381 -0
- package/dist/chunks/semantic-agent-HK5X6CKU.js +6381 -0
- package/dist/chunks/semantic-agent-KONIKEGW.js +6381 -0
- package/dist/chunks/semantic-agent-LH6IZ2L7.js +137 -0
- package/dist/chunks/semantic-tool-handlers-5LMSH2U7.js +3 -0
- package/dist/chunks/semantic-tool-handlers-735UMO7Y.js +817 -0
- package/dist/chunks/semantic-tool-handlers-BNUYPP7X.js +817 -0
- package/dist/chunks/semantic-tool-handlers-MYZPEUD2.js +817 -0
- package/dist/chunks/snapshot-tool-handlers-6SIHZT2F.js +201 -0
- package/dist/chunks/snapshot-tool-handlers-DS4P3KOT.js +201 -0
- package/dist/chunks/snapshot-tool-handlers-JYHRFPC7.js +201 -0
- package/dist/chunks/snapshot-tool-handlers-YEHMAT3L.js +1 -0
- package/dist/chunks/storage-paths-A3C7WHHG.js +8 -0
- package/dist/chunks/storage-paths-HDYH7WPM.js +1 -0
- package/dist/chunks/storage-paths-IMFRHBWF.js +8 -0
- package/dist/chunks/storage-paths-P3PUSMUD.js +8 -0
- package/dist/chunks/taint-tool-handlers-CWESOOMQ.js +68 -0
- package/dist/chunks/taint-tool-handlers-OG3NVVP3.js +1 -0
- package/dist/chunks/taint-tool-handlers-ON3G3FA7.js +68 -0
- package/dist/chunks/taint-tool-handlers-P4P5J6DB.js +68 -0
- package/dist/chunks/tracing-tool-handlers-4BDCXTZZ.js +3935 -0
- package/dist/chunks/tracing-tool-handlers-6FPNM7HX.js +3935 -0
- package/dist/chunks/tracing-tool-handlers-LQTQ5SKK.js +89 -0
- package/dist/chunks/tracing-tool-handlers-XRQX2DTS.js +3935 -0
- package/dist/chunks/validation-tool-handlers-DZUG7KYY.js +2 -0
- package/dist/chunks/validation-tool-handlers-O6TGFSH5.js +555 -0
- package/dist/chunks/validation-tool-handlers-RREUYKIR.js +555 -0
- package/dist/chunks/validation-tool-handlers-XPWSMS37.js +555 -0
- package/dist/index.js +13 -13
- package/dist/roslyn-addon/.build-hash +1 -1
- package/dist/roslyn-addon/ILGPU.Algorithms.dll +0 -0
- package/dist/roslyn-addon/ILGPU.dll +0 -0
- package/dist/roslyn-addon/UltraCode.CSharp.deps.json +35 -0
- package/dist/roslyn-addon/UltraCode.CSharp.dll +0 -0
- package/package.json +1 -1
|
@@ -0,0 +1,817 @@
|
|
|
1
|
+
import { DetectCodeClonesSchema } from './chunk-RAGUL4TA.js';
|
|
2
|
+
import { projectPathParam } from './chunk-NJUB245U.js';
|
|
3
|
+
import { SAFE_LIMITS, BaseToolHandler, MAX_PAGE_SIZE, paginate } from './chunk-VS44D772.js';
|
|
4
|
+
import './chunk-TUWE6FCW.js';
|
|
5
|
+
import './chunk-TVOTA7EE.js';
|
|
6
|
+
import './chunk-HEMJHRHZ.js';
|
|
7
|
+
import { toError } from './chunk-5WKPA33T.js';
|
|
8
|
+
import { init_logging, log } from './chunk-VCCBEJQ5.js';
|
|
9
|
+
import './chunk-NAQKA54E.js';
|
|
10
|
+
import { readFileSync } from 'fs';
|
|
11
|
+
import { z } from 'zod';
|
|
12
|
+
|
|
13
|
+
// src/tools/handlers/semantic-tool-handlers.ts
|
|
14
|
+
init_logging();
|
|
15
|
+
var CONTENT_TOKEN_LIMIT = 8e3;
|
|
16
|
+
var CHARS_PER_TOKEN = 4;
|
|
17
|
+
function loadSourceCode(filePath, startLine, endLine) {
|
|
18
|
+
if (!filePath || !startLine || !endLine) return void 0;
|
|
19
|
+
try {
|
|
20
|
+
const content = readFileSync(filePath, "utf-8");
|
|
21
|
+
const lines = content.split("\n");
|
|
22
|
+
const start = Math.max(0, startLine - 1);
|
|
23
|
+
const end = Math.min(lines.length, endLine);
|
|
24
|
+
return lines.slice(start, end).join("\n");
|
|
25
|
+
} catch {
|
|
26
|
+
return void 0;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function estimateTokens(text) {
|
|
30
|
+
return Math.ceil(text.length / CHARS_PER_TOKEN);
|
|
31
|
+
}
|
|
32
|
+
function applyContentPagination(results, includeContent) {
|
|
33
|
+
if (!includeContent || results.length === 0) {
|
|
34
|
+
return { results };
|
|
35
|
+
}
|
|
36
|
+
let tokensUsed = 0;
|
|
37
|
+
let includedCount = 0;
|
|
38
|
+
const paginatedResults = [];
|
|
39
|
+
for (const result of results) {
|
|
40
|
+
const content = result.content;
|
|
41
|
+
if (content) {
|
|
42
|
+
const contentTokens = estimateTokens(content);
|
|
43
|
+
if (tokensUsed + contentTokens > CONTENT_TOKEN_LIMIT && includedCount > 0) {
|
|
44
|
+
paginatedResults.push({ ...result, content: void 0 });
|
|
45
|
+
} else {
|
|
46
|
+
tokensUsed += contentTokens;
|
|
47
|
+
includedCount++;
|
|
48
|
+
paginatedResults.push(result);
|
|
49
|
+
}
|
|
50
|
+
} else {
|
|
51
|
+
paginatedResults.push(result);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const hasMore = includedCount < results.filter((r) => r.content).length;
|
|
55
|
+
return {
|
|
56
|
+
results: paginatedResults,
|
|
57
|
+
...hasMore ? {
|
|
58
|
+
contentPagination: {
|
|
59
|
+
includedCount,
|
|
60
|
+
totalCount: results.length,
|
|
61
|
+
tokensUsed,
|
|
62
|
+
tokenLimit: CONTENT_TOKEN_LIMIT,
|
|
63
|
+
hasMore,
|
|
64
|
+
message: `Content included for ${includedCount} of ${results.length} results (~${tokensUsed} tokens). Use offset to see more.`
|
|
65
|
+
}
|
|
66
|
+
} : {}
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
var SemanticSearchSchema = z.object({
|
|
70
|
+
query: z.string().describe("Natural language search query"),
|
|
71
|
+
projectPath: projectPathParam,
|
|
72
|
+
offset: z.number().optional().default(0),
|
|
73
|
+
limit: z.number().optional().default(SAFE_LIMITS.searchResults),
|
|
74
|
+
entityTypes: z.array(z.string()).optional().describe("Filter by entity types (function, class, interface, etc.)"),
|
|
75
|
+
minSimilarity: z.number().optional().default(0.7).describe("Minimum similarity threshold (0.0-1.0)"),
|
|
76
|
+
includeContent: z.boolean().optional().default(false).describe("Include full source code (startLine to endLine) in results"),
|
|
77
|
+
expandRelated: z.boolean().optional().default(false).describe("Expand results with graph neighbors (callers, dependencies, inheritors)"),
|
|
78
|
+
expansionDepth: z.number().optional().default(1).describe("Graph traversal depth for expansion (1 or 2 hops)"),
|
|
79
|
+
// Two-stage retrieval with reranking
|
|
80
|
+
rerank: z.boolean().optional().default(false).describe(
|
|
81
|
+
"Enable two-stage retrieval: rerank top results with cross-encoder for better precision (requires vLLM or TEI provider)"
|
|
82
|
+
),
|
|
83
|
+
rerankTopK: z.number().optional().default(50).describe("Number of top embedding results to rerank (default: 50)"),
|
|
84
|
+
// New filters based on parser-extracted data
|
|
85
|
+
minCyclomatic: z.number().optional().describe("Filter: minimum cyclomatic complexity"),
|
|
86
|
+
maxCyclomatic: z.number().optional().describe("Filter: maximum cyclomatic complexity"),
|
|
87
|
+
hasExceptions: z.boolean().optional().describe("Filter: must have try-catch blocks"),
|
|
88
|
+
hasLoops: z.boolean().optional().describe("Filter: must have loops"),
|
|
89
|
+
hasAwaits: z.boolean().optional().describe("Filter: must have await expressions (async code)"),
|
|
90
|
+
hasDocumentation: z.boolean().optional().describe("Filter: must have documentation/docstrings"),
|
|
91
|
+
isDeprecated: z.boolean().optional().describe("Filter: deprecated entities only"),
|
|
92
|
+
minCallCount: z.number().optional().describe("Filter: minimum number of function calls"),
|
|
93
|
+
// History filters (Prolly Tree)
|
|
94
|
+
changedInLastCommits: z.number().optional().describe("Filter: only entities changed in last N graph commits (Prolly Tree)"),
|
|
95
|
+
changedSinceMs: z.number().optional().describe("Filter: only entities changed since this Unix timestamp (ms)")
|
|
96
|
+
});
|
|
97
|
+
var SemanticSearchToolHandler = class extends BaseToolHandler {
|
|
98
|
+
parseArgs(args) {
|
|
99
|
+
return SemanticSearchSchema.parse(args);
|
|
100
|
+
}
|
|
101
|
+
async execute(args) {
|
|
102
|
+
const resolvedPath = this.resolveProjectPath(args);
|
|
103
|
+
const currentProject = this.getProjectContext().getCurrentProject();
|
|
104
|
+
log.d("SEMSEARCH", "proj_paths", { arg: args.projectPath, resolved: resolvedPath, current: currentProject });
|
|
105
|
+
if (args.projectPath && resolvedPath !== currentProject) {
|
|
106
|
+
if (!this.isProjectIndexed(resolvedPath)) {
|
|
107
|
+
return {
|
|
108
|
+
content: [
|
|
109
|
+
{
|
|
110
|
+
type: "text",
|
|
111
|
+
text: JSON.stringify(
|
|
112
|
+
{
|
|
113
|
+
success: false,
|
|
114
|
+
error: `Project not indexed: ${resolvedPath}`,
|
|
115
|
+
hint: "Run 'index' tool on the target directory first",
|
|
116
|
+
currentProject,
|
|
117
|
+
requestedProject: resolvedPath
|
|
118
|
+
},
|
|
119
|
+
null,
|
|
120
|
+
2
|
|
121
|
+
)
|
|
122
|
+
}
|
|
123
|
+
]
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
log.w("SEMSEARCH", "cross_proj", { current: currentProject, requested: resolvedPath });
|
|
127
|
+
}
|
|
128
|
+
const semanticAgent = await this.ensureSemanticAgentForProject(resolvedPath);
|
|
129
|
+
const initError = semanticAgent.getEmbeddingInitError();
|
|
130
|
+
if (initError) {
|
|
131
|
+
return {
|
|
132
|
+
content: [
|
|
133
|
+
{
|
|
134
|
+
type: "text",
|
|
135
|
+
text: JSON.stringify(
|
|
136
|
+
{
|
|
137
|
+
success: false,
|
|
138
|
+
error: `Embedding provider initialization failed: ${initError.message}`,
|
|
139
|
+
hint: "Check if the configured embedding provider is available (Docker, Ollama, etc.)"
|
|
140
|
+
},
|
|
141
|
+
null,
|
|
142
|
+
2
|
|
143
|
+
)
|
|
144
|
+
}
|
|
145
|
+
]
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
await this.ensureGraphStorageForProject(resolvedPath);
|
|
149
|
+
const safeLimit = Math.min(args.limit, MAX_PAGE_SIZE);
|
|
150
|
+
const searchResult = await semanticAgent.semanticSearch(args.query, 1e3);
|
|
151
|
+
let allResults = searchResult.results || [];
|
|
152
|
+
let rerankStats = { reranked: false, provider: "" };
|
|
153
|
+
if (args.rerank && allResults.length > 0) {
|
|
154
|
+
const provider = semanticAgent.getEmbeddingProvider?.();
|
|
155
|
+
const capabilities = provider?.getCapabilities?.();
|
|
156
|
+
if (capabilities?.rerank && provider?.rerank) {
|
|
157
|
+
try {
|
|
158
|
+
const topK = Math.min(args.rerankTopK, allResults.length);
|
|
159
|
+
const toRerank = allResults.slice(0, topK);
|
|
160
|
+
const documents = toRerank.map((r, idx) => ({
|
|
161
|
+
text: r.content || r.metadata?.content || r.name || "",
|
|
162
|
+
id: r.id || String(idx)
|
|
163
|
+
}));
|
|
164
|
+
const reranked = await provider.rerank(args.query, documents, {
|
|
165
|
+
topK,
|
|
166
|
+
threshold: args.minSimilarity
|
|
167
|
+
});
|
|
168
|
+
const rerankedMap = new Map(reranked.map((r) => [r.id, r.score]));
|
|
169
|
+
for (const result of toRerank) {
|
|
170
|
+
const newScore = rerankedMap.get(result.id);
|
|
171
|
+
if (newScore !== void 0) {
|
|
172
|
+
result.similarity = newScore;
|
|
173
|
+
result.reranked = true;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
allResults = [...toRerank, ...allResults.slice(topK)];
|
|
177
|
+
allResults.sort(
|
|
178
|
+
(a, b) => (b.similarity || 0) - (a.similarity || 0)
|
|
179
|
+
);
|
|
180
|
+
rerankStats = { reranked: true, provider: provider.info?.name || "unknown" };
|
|
181
|
+
} catch (error) {
|
|
182
|
+
const err = toError(error);
|
|
183
|
+
log.w("SEMSEARCH", "rerank_fail", { err: err.message });
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
let filteredResults = allResults;
|
|
188
|
+
const hasFilters = args.minCyclomatic !== void 0 || args.maxCyclomatic !== void 0 || args.hasExceptions !== void 0 || args.hasLoops !== void 0 || args.hasAwaits !== void 0 || args.hasDocumentation !== void 0 || args.isDeprecated !== void 0 || args.minCallCount !== void 0;
|
|
189
|
+
if (hasFilters) {
|
|
190
|
+
filteredResults = allResults.filter((r) => {
|
|
191
|
+
const meta = r.metadata || {};
|
|
192
|
+
if (args.minCyclomatic !== void 0 && (meta.cyclomatic || 0) < args.minCyclomatic) return false;
|
|
193
|
+
if (args.maxCyclomatic !== void 0 && (meta.cyclomatic || Infinity) > args.maxCyclomatic) return false;
|
|
194
|
+
if (args.hasExceptions !== void 0 && meta.hasExceptions !== args.hasExceptions) return false;
|
|
195
|
+
if (args.hasLoops !== void 0 && meta.hasLoops !== args.hasLoops) return false;
|
|
196
|
+
if (args.hasAwaits !== void 0 && meta.hasAwaits !== args.hasAwaits) return false;
|
|
197
|
+
if (args.hasDocumentation !== void 0 && meta.hasDocumentation !== args.hasDocumentation) return false;
|
|
198
|
+
if (args.isDeprecated !== void 0 && meta.isDeprecated !== args.isDeprecated) return false;
|
|
199
|
+
if (args.minCallCount !== void 0 && (meta.callCount || 0) < args.minCallCount) return false;
|
|
200
|
+
return true;
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
if (args.changedInLastCommits !== void 0 || args.changedSinceMs !== void 0) {
|
|
204
|
+
const { getRecentlyChangedEntities } = await import('./recently-changed-FX5QR4Z2.js');
|
|
205
|
+
const storage = await this.context.getGraphStorage();
|
|
206
|
+
const adapter = storage.getLibSQLAdapter?.();
|
|
207
|
+
if (adapter) {
|
|
208
|
+
const recentlyChanged = await getRecentlyChangedEntities(adapter, {
|
|
209
|
+
lastCommits: args.changedInLastCommits,
|
|
210
|
+
sinceTimestamp: args.changedSinceMs
|
|
211
|
+
});
|
|
212
|
+
if (recentlyChanged) {
|
|
213
|
+
filteredResults = filteredResults.filter((r) => {
|
|
214
|
+
const entityId = r.metadata?.entityId || r.id?.replace(/^ent:/, "");
|
|
215
|
+
return entityId ? recentlyChanged.changedIds.has(entityId) : false;
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
let expandedResults = filteredResults;
|
|
221
|
+
let expansionStats = { expanded: false, neighborsAdded: 0 };
|
|
222
|
+
if (args.expandRelated && filteredResults.length > 0) {
|
|
223
|
+
const expansion = await this.expandWithGraphNeighbors(filteredResults, args.expansionDepth, args.minSimilarity);
|
|
224
|
+
expandedResults = expansion.results;
|
|
225
|
+
expansionStats = { expanded: true, neighborsAdded: expansion.neighborsAdded };
|
|
226
|
+
}
|
|
227
|
+
const paginatedResult = paginate(expandedResults, args.offset, safeLimit);
|
|
228
|
+
const queryExpansion = searchResult.expandedQuery ? {
|
|
229
|
+
expandedQuery: searchResult.expandedQuery,
|
|
230
|
+
...searchResult.expansionInfo ? {
|
|
231
|
+
coocTerms: searchResult.expansionInfo.coocTerms?.length || 0,
|
|
232
|
+
prfTerms: searchResult.expansionInfo.prfTerms?.length || 0
|
|
233
|
+
} : {}
|
|
234
|
+
} : null;
|
|
235
|
+
const mappedResults = paginatedResult.data.map((r) => {
|
|
236
|
+
const meta = r.metadata || {};
|
|
237
|
+
const filePath = r.filePath || meta.filePath || meta.path;
|
|
238
|
+
const startLine = meta.startLine;
|
|
239
|
+
const endLine = meta.endLine;
|
|
240
|
+
const content = args.includeContent ? loadSourceCode(filePath, startLine, endLine) : void 0;
|
|
241
|
+
return {
|
|
242
|
+
id: r.id,
|
|
243
|
+
name: r.name || meta.name,
|
|
244
|
+
type: r.type || meta.entityType || meta.type,
|
|
245
|
+
similarity: r.similarity,
|
|
246
|
+
...r.reranked ? { reranked: true } : {},
|
|
247
|
+
filePath,
|
|
248
|
+
startLine,
|
|
249
|
+
endLine,
|
|
250
|
+
language: meta.language,
|
|
251
|
+
// Complexity metrics (if available)
|
|
252
|
+
...meta.cyclomatic ? {
|
|
253
|
+
complexity: {
|
|
254
|
+
cyclomatic: meta.cyclomatic,
|
|
255
|
+
cognitive: meta.cognitive,
|
|
256
|
+
linesOfCode: meta.linesOfCode,
|
|
257
|
+
nestingDepth: meta.nestingDepth
|
|
258
|
+
}
|
|
259
|
+
} : {},
|
|
260
|
+
// Control flow info (if available)
|
|
261
|
+
...meta.hasBranches !== void 0 ? {
|
|
262
|
+
controlFlow: {
|
|
263
|
+
hasBranches: meta.hasBranches,
|
|
264
|
+
hasLoops: meta.hasLoops,
|
|
265
|
+
hasExceptions: meta.hasExceptions,
|
|
266
|
+
hasAwaits: meta.hasAwaits,
|
|
267
|
+
branchCount: meta.branchCount,
|
|
268
|
+
loopCount: meta.loopCount,
|
|
269
|
+
returnCount: meta.returnCount
|
|
270
|
+
}
|
|
271
|
+
} : {},
|
|
272
|
+
// Call info (if available)
|
|
273
|
+
...meta.callCount ? {
|
|
274
|
+
calls: {
|
|
275
|
+
count: meta.callCount,
|
|
276
|
+
hasAsync: meta.hasAsyncCalls
|
|
277
|
+
}
|
|
278
|
+
} : {},
|
|
279
|
+
// Documentation info (if available)
|
|
280
|
+
...meta.hasDocumentation ? {
|
|
281
|
+
documentation: {
|
|
282
|
+
hasDocumentation: true,
|
|
283
|
+
hasParams: meta.hasParams,
|
|
284
|
+
hasExamples: meta.hasExamples,
|
|
285
|
+
isDeprecated: meta.isDeprecated
|
|
286
|
+
}
|
|
287
|
+
} : {},
|
|
288
|
+
// Type info
|
|
289
|
+
...meta.returnType ? { returnType: meta.returnType } : {},
|
|
290
|
+
...meta.paramCount ? { paramCount: meta.paramCount } : {},
|
|
291
|
+
// Expansion info
|
|
292
|
+
...r.isExpanded ? { isExpanded: true, relationshipType: r.relationshipType } : {},
|
|
293
|
+
// Content (loaded from file)
|
|
294
|
+
...content ? { content } : {}
|
|
295
|
+
};
|
|
296
|
+
});
|
|
297
|
+
const { results: finalResults, contentPagination } = applyContentPagination(mappedResults, args.includeContent);
|
|
298
|
+
return {
|
|
299
|
+
content: [
|
|
300
|
+
{
|
|
301
|
+
type: "text",
|
|
302
|
+
text: JSON.stringify(
|
|
303
|
+
{
|
|
304
|
+
query: args.query,
|
|
305
|
+
count: finalResults.length,
|
|
306
|
+
pagination: paginatedResult.pagination,
|
|
307
|
+
...queryExpansion ? { queryExpansion } : {},
|
|
308
|
+
...rerankStats.reranked ? { rerank: rerankStats } : {},
|
|
309
|
+
...expansionStats.expanded ? { expansion: expansionStats } : {},
|
|
310
|
+
...contentPagination ? { contentPagination } : {},
|
|
311
|
+
results: finalResults
|
|
312
|
+
},
|
|
313
|
+
null,
|
|
314
|
+
2
|
|
315
|
+
)
|
|
316
|
+
}
|
|
317
|
+
]
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Expand search results with graph neighbors (callers, dependencies, inheritors)
|
|
322
|
+
*/
|
|
323
|
+
async expandWithGraphNeighbors(results, depth, minSimilarity) {
|
|
324
|
+
const storage = await this.context.getGraphStorage();
|
|
325
|
+
const seen = new Set(results.map((r) => r.id));
|
|
326
|
+
const neighbors = [];
|
|
327
|
+
for (const result of results.slice(0, 20)) {
|
|
328
|
+
let entityId = result.metadata?.entityId;
|
|
329
|
+
if (!entityId && result.metadata?.name && result.metadata?.path) {
|
|
330
|
+
try {
|
|
331
|
+
const found = await storage.findEntities({
|
|
332
|
+
filters: {
|
|
333
|
+
name: result.metadata.name,
|
|
334
|
+
filePath: result.metadata.path
|
|
335
|
+
},
|
|
336
|
+
limit: 1
|
|
337
|
+
});
|
|
338
|
+
if (found.length > 0) {
|
|
339
|
+
entityId = found[0]?.id;
|
|
340
|
+
}
|
|
341
|
+
} catch {
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
if (!entityId) continue;
|
|
345
|
+
try {
|
|
346
|
+
const relationships = await storage.getRelationshipsForEntity(entityId);
|
|
347
|
+
for (const rel of relationships) {
|
|
348
|
+
const relatedId = rel.fromId === entityId ? rel.toId : rel.fromId;
|
|
349
|
+
if (seen.has(relatedId) || seen.has(`ent:${relatedId}`)) continue;
|
|
350
|
+
seen.add(relatedId);
|
|
351
|
+
const relatedEntity = await storage.getEntity(relatedId);
|
|
352
|
+
if (!relatedEntity) continue;
|
|
353
|
+
const neighborSimilarity = result.similarity * 0.7;
|
|
354
|
+
if (neighborSimilarity < minSimilarity) continue;
|
|
355
|
+
neighbors.push({
|
|
356
|
+
id: `ent:${relatedId}`,
|
|
357
|
+
name: relatedEntity.name,
|
|
358
|
+
type: relatedEntity.type,
|
|
359
|
+
similarity: neighborSimilarity,
|
|
360
|
+
filePath: relatedEntity.filePath,
|
|
361
|
+
content: relatedEntity.metadata?.["content"],
|
|
362
|
+
isExpanded: true,
|
|
363
|
+
relationshipType: rel.type,
|
|
364
|
+
metadata: { entityId: relatedId }
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
if (depth >= 2 && neighbors.length < 50) {
|
|
368
|
+
for (const neighbor of neighbors.slice(-10)) {
|
|
369
|
+
const neighborEntityId = neighbor.id?.replace(/^ent:/, "");
|
|
370
|
+
if (!neighborEntityId) continue;
|
|
371
|
+
try {
|
|
372
|
+
const hop2Rels = await storage.getRelationshipsForEntity(neighborEntityId);
|
|
373
|
+
for (const rel of hop2Rels.slice(0, 5)) {
|
|
374
|
+
const hop2Id = rel.fromId === neighborEntityId ? rel.toId : rel.fromId;
|
|
375
|
+
if (seen.has(hop2Id) || seen.has(`ent:${hop2Id}`)) continue;
|
|
376
|
+
seen.add(hop2Id);
|
|
377
|
+
const hop2Entity = await storage.getEntity(hop2Id);
|
|
378
|
+
if (!hop2Entity) continue;
|
|
379
|
+
const hop2Similarity = neighbor.similarity * 0.7;
|
|
380
|
+
if (hop2Similarity < minSimilarity) continue;
|
|
381
|
+
neighbors.push({
|
|
382
|
+
id: `ent:${hop2Id}`,
|
|
383
|
+
name: hop2Entity.name,
|
|
384
|
+
type: hop2Entity.type,
|
|
385
|
+
similarity: hop2Similarity,
|
|
386
|
+
filePath: hop2Entity.filePath,
|
|
387
|
+
content: hop2Entity.metadata?.["content"],
|
|
388
|
+
isExpanded: true,
|
|
389
|
+
relationshipType: `${rel.type} (2-hop)`,
|
|
390
|
+
metadata: { entityId: hop2Id }
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
} catch {
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
} catch {
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
const combined = [...results, ...neighbors];
|
|
401
|
+
combined.sort((a, b) => (b.similarity || 0) - (a.similarity || 0));
|
|
402
|
+
return {
|
|
403
|
+
results: combined,
|
|
404
|
+
neighborsAdded: neighbors.length
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
};
|
|
408
|
+
var FindSimilarCodeSchema = z.object({
|
|
409
|
+
code: z.string().describe("Code snippet to find similar code for"),
|
|
410
|
+
projectPath: projectPathParam,
|
|
411
|
+
offset: z.number().optional().default(0),
|
|
412
|
+
limit: z.number().optional().default(SAFE_LIMITS.searchResults),
|
|
413
|
+
minSimilarity: z.number().optional().default(0.7).describe("Minimum similarity threshold (0.0-1.0)"),
|
|
414
|
+
includeContent: z.boolean().optional().default(false).describe("Include full source code (startLine to endLine) in results")
|
|
415
|
+
});
|
|
416
|
+
var FindSimilarCodeToolHandler = class extends BaseToolHandler {
|
|
417
|
+
parseArgs(args) {
|
|
418
|
+
return FindSimilarCodeSchema.parse(args);
|
|
419
|
+
}
|
|
420
|
+
async execute(args) {
|
|
421
|
+
const resolvedPath = this.resolveProjectPath(args);
|
|
422
|
+
const semanticAgent = await this.ensureSemanticAgentForProject(resolvedPath);
|
|
423
|
+
const initError = semanticAgent.getEmbeddingInitError();
|
|
424
|
+
if (initError) {
|
|
425
|
+
return {
|
|
426
|
+
content: [
|
|
427
|
+
{
|
|
428
|
+
type: "text",
|
|
429
|
+
text: JSON.stringify(
|
|
430
|
+
{
|
|
431
|
+
success: false,
|
|
432
|
+
error: `Embedding provider initialization failed: ${initError.message}`,
|
|
433
|
+
hint: "Check if the configured embedding provider is available (Docker, Ollama, etc.)"
|
|
434
|
+
},
|
|
435
|
+
null,
|
|
436
|
+
2
|
|
437
|
+
)
|
|
438
|
+
}
|
|
439
|
+
]
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
const safeLimit = Math.min(args.limit, MAX_PAGE_SIZE);
|
|
443
|
+
const allResults = await semanticAgent.findSimilarCode(args.code, args.minSimilarity);
|
|
444
|
+
const paginatedResult = paginate(allResults, args.offset, safeLimit);
|
|
445
|
+
const mappedResults = paginatedResult.data.map((r) => {
|
|
446
|
+
const filePath = r.filePath || r.metadata?.path;
|
|
447
|
+
const startLine = r.metadata?.startLine;
|
|
448
|
+
const endLine = r.metadata?.endLine;
|
|
449
|
+
const content = args.includeContent ? loadSourceCode(filePath, startLine, endLine) : void 0;
|
|
450
|
+
return {
|
|
451
|
+
id: r.id,
|
|
452
|
+
name: r.name,
|
|
453
|
+
type: r.type,
|
|
454
|
+
similarity: r.similarity,
|
|
455
|
+
filePath,
|
|
456
|
+
startLine,
|
|
457
|
+
endLine,
|
|
458
|
+
...content ? { content } : {}
|
|
459
|
+
};
|
|
460
|
+
});
|
|
461
|
+
const { results: finalResults, contentPagination } = applyContentPagination(mappedResults, args.includeContent);
|
|
462
|
+
return {
|
|
463
|
+
content: [
|
|
464
|
+
{
|
|
465
|
+
type: "text",
|
|
466
|
+
text: JSON.stringify(
|
|
467
|
+
{
|
|
468
|
+
count: finalResults.length,
|
|
469
|
+
pagination: paginatedResult.pagination,
|
|
470
|
+
...contentPagination ? { contentPagination } : {},
|
|
471
|
+
results: finalResults
|
|
472
|
+
},
|
|
473
|
+
null,
|
|
474
|
+
2
|
|
475
|
+
)
|
|
476
|
+
}
|
|
477
|
+
]
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
};
|
|
481
|
+
var DetectCodeClonesToolHandler = class extends BaseToolHandler {
|
|
482
|
+
parseArgs(args) {
|
|
483
|
+
return DetectCodeClonesSchema.parse(args);
|
|
484
|
+
}
|
|
485
|
+
async execute(args) {
|
|
486
|
+
try {
|
|
487
|
+
const semanticAgent = await this.ensureSemanticAgentForProject();
|
|
488
|
+
const initError = semanticAgent.getEmbeddingInitError();
|
|
489
|
+
if (initError) {
|
|
490
|
+
return {
|
|
491
|
+
content: [
|
|
492
|
+
{
|
|
493
|
+
type: "text",
|
|
494
|
+
text: JSON.stringify(
|
|
495
|
+
{
|
|
496
|
+
success: false,
|
|
497
|
+
error: `Embedding provider initialization failed: ${initError.message}`,
|
|
498
|
+
hint: "Check if the configured embedding provider is available (Docker, Ollama, etc.)"
|
|
499
|
+
},
|
|
500
|
+
null,
|
|
501
|
+
2
|
|
502
|
+
)
|
|
503
|
+
}
|
|
504
|
+
]
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
const minSimilarity = args.minSimilarity ?? 0.8;
|
|
508
|
+
const allClones = await semanticAgent.detectClones(minSimilarity);
|
|
509
|
+
if (!allClones || !Array.isArray(allClones)) {
|
|
510
|
+
return {
|
|
511
|
+
content: [
|
|
512
|
+
{
|
|
513
|
+
type: "text",
|
|
514
|
+
text: JSON.stringify(
|
|
515
|
+
{
|
|
516
|
+
groupsFound: 0,
|
|
517
|
+
clones: [],
|
|
518
|
+
warning: "Clone detection unavailable - vector store may not be initialized"
|
|
519
|
+
},
|
|
520
|
+
null,
|
|
521
|
+
2
|
|
522
|
+
)
|
|
523
|
+
}
|
|
524
|
+
]
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
return {
|
|
528
|
+
content: [
|
|
529
|
+
{
|
|
530
|
+
type: "text",
|
|
531
|
+
text: JSON.stringify(
|
|
532
|
+
{
|
|
533
|
+
groupsFound: allClones.length,
|
|
534
|
+
scope: args.scope ?? "all",
|
|
535
|
+
minSimilarity,
|
|
536
|
+
clones: allClones.map((group) => ({
|
|
537
|
+
similarity: group.avgSimilarity,
|
|
538
|
+
cloneType: group.cloneType,
|
|
539
|
+
members: (group.members || []).map((m) => ({
|
|
540
|
+
id: m.id,
|
|
541
|
+
name: m.name,
|
|
542
|
+
filePath: m.path,
|
|
543
|
+
startLine: m.startLine,
|
|
544
|
+
endLine: m.endLine
|
|
545
|
+
}))
|
|
546
|
+
}))
|
|
547
|
+
},
|
|
548
|
+
null,
|
|
549
|
+
2
|
|
550
|
+
)
|
|
551
|
+
}
|
|
552
|
+
]
|
|
553
|
+
};
|
|
554
|
+
} catch (error) {
|
|
555
|
+
const err = toError(error);
|
|
556
|
+
log.e("CLONES", "detectClones failed", { error: err.message, stack: err.stack });
|
|
557
|
+
return {
|
|
558
|
+
content: [
|
|
559
|
+
{
|
|
560
|
+
type: "text",
|
|
561
|
+
text: JSON.stringify(
|
|
562
|
+
{
|
|
563
|
+
groupsFound: 0,
|
|
564
|
+
clones: [],
|
|
565
|
+
error: err.message
|
|
566
|
+
},
|
|
567
|
+
null,
|
|
568
|
+
2
|
|
569
|
+
)
|
|
570
|
+
}
|
|
571
|
+
]
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
};
|
|
576
|
+
var JscpdDetectClonesSchema = z.object({
|
|
577
|
+
directory: z.string().optional(),
|
|
578
|
+
minLines: z.number().optional().default(5),
|
|
579
|
+
minTokens: z.number().optional().default(50),
|
|
580
|
+
threshold: z.number().optional().default(0),
|
|
581
|
+
format: z.array(z.string()).optional(),
|
|
582
|
+
offset: z.number().optional().default(0),
|
|
583
|
+
limit: z.number().optional().default(SAFE_LIMITS.clones)
|
|
584
|
+
});
|
|
585
|
+
var JscpdDetectClonesToolHandler = class extends BaseToolHandler {
|
|
586
|
+
parseArgs(args) {
|
|
587
|
+
return JscpdDetectClonesSchema.parse(args);
|
|
588
|
+
}
|
|
589
|
+
async execute(args) {
|
|
590
|
+
const targetDir = args.directory ? this.context.normalizeInputPath(args.directory) ?? this.resolveProjectPath({}) : this.resolveProjectPath({});
|
|
591
|
+
try {
|
|
592
|
+
const { runJscpdCloneDetection } = await import('./jscpd-ZS3WMD6W.js');
|
|
593
|
+
const result = await runJscpdCloneDetection({
|
|
594
|
+
paths: [targetDir],
|
|
595
|
+
formats: args.format || ["javascript", "typescript", "python"],
|
|
596
|
+
minLines: args.minLines,
|
|
597
|
+
minTokens: args.minTokens
|
|
598
|
+
});
|
|
599
|
+
const safeLimit = Math.min(args.limit, MAX_PAGE_SIZE);
|
|
600
|
+
const paginatedResult = paginate(result.clones, args.offset, safeLimit);
|
|
601
|
+
return {
|
|
602
|
+
content: [
|
|
603
|
+
{
|
|
604
|
+
type: "text",
|
|
605
|
+
text: JSON.stringify(
|
|
606
|
+
{
|
|
607
|
+
duplicatesFound: paginatedResult.data.length,
|
|
608
|
+
pagination: paginatedResult.pagination,
|
|
609
|
+
statistics: {
|
|
610
|
+
total: result.statistic.total,
|
|
611
|
+
detectionDate: result.statistic.detectionDate
|
|
612
|
+
},
|
|
613
|
+
duplicates: paginatedResult.data.map((c) => ({
|
|
614
|
+
format: c.format,
|
|
615
|
+
foundDate: c.foundDate,
|
|
616
|
+
duplicationA: {
|
|
617
|
+
sourceId: c.duplicationA.sourceId,
|
|
618
|
+
start: c.duplicationA.start,
|
|
619
|
+
end: c.duplicationA.end
|
|
620
|
+
},
|
|
621
|
+
duplicationB: {
|
|
622
|
+
sourceId: c.duplicationB.sourceId,
|
|
623
|
+
start: c.duplicationB.start,
|
|
624
|
+
end: c.duplicationB.end
|
|
625
|
+
}
|
|
626
|
+
}))
|
|
627
|
+
},
|
|
628
|
+
null,
|
|
629
|
+
2
|
|
630
|
+
)
|
|
631
|
+
}
|
|
632
|
+
]
|
|
633
|
+
};
|
|
634
|
+
} catch (error) {
|
|
635
|
+
const err = toError(error);
|
|
636
|
+
return {
|
|
637
|
+
content: [
|
|
638
|
+
{
|
|
639
|
+
type: "text",
|
|
640
|
+
text: JSON.stringify({ error: err.message })
|
|
641
|
+
}
|
|
642
|
+
]
|
|
643
|
+
};
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
};
|
|
647
|
+
var CrossLanguageSearchSchema = z.object({
|
|
648
|
+
query: z.string().describe("Search query"),
|
|
649
|
+
projectPath: projectPathParam,
|
|
650
|
+
languages: z.array(z.string()).optional().describe("Languages to search in"),
|
|
651
|
+
offset: z.number().optional().default(0),
|
|
652
|
+
limit: z.number().optional().default(SAFE_LIMITS.searchResults),
|
|
653
|
+
includeContent: z.boolean().optional().default(false).describe("Include full source code (startLine to endLine) in results")
|
|
654
|
+
});
|
|
655
|
+
var CrossLanguageSearchToolHandler = class extends BaseToolHandler {
|
|
656
|
+
parseArgs(args) {
|
|
657
|
+
return CrossLanguageSearchSchema.parse(args);
|
|
658
|
+
}
|
|
659
|
+
async execute(args) {
|
|
660
|
+
const resolvedPath = this.resolveProjectPath(args);
|
|
661
|
+
const semanticAgent = await this.ensureSemanticAgentForProject(resolvedPath);
|
|
662
|
+
const safeLimit = Math.min(args.limit, MAX_PAGE_SIZE);
|
|
663
|
+
const languages = args.languages || [
|
|
664
|
+
"typescript",
|
|
665
|
+
"javascript",
|
|
666
|
+
"python",
|
|
667
|
+
"go",
|
|
668
|
+
"rust",
|
|
669
|
+
"java",
|
|
670
|
+
"cpp",
|
|
671
|
+
"swift",
|
|
672
|
+
"kotlin",
|
|
673
|
+
"csharp"
|
|
674
|
+
];
|
|
675
|
+
const allResults = await semanticAgent.crossLanguageSearch(args.query, languages);
|
|
676
|
+
const paginatedResult = paginate(allResults, args.offset, safeLimit);
|
|
677
|
+
const mappedResults = paginatedResult.data.map((r) => {
|
|
678
|
+
const filePath = r.filePath || r.metadata?.path;
|
|
679
|
+
const startLine = r.metadata?.startLine;
|
|
680
|
+
const endLine = r.metadata?.endLine;
|
|
681
|
+
const content = args.includeContent ? loadSourceCode(filePath, startLine, endLine) : void 0;
|
|
682
|
+
return {
|
|
683
|
+
id: r.id,
|
|
684
|
+
name: r.name,
|
|
685
|
+
language: r.metadata?.language,
|
|
686
|
+
filePath,
|
|
687
|
+
startLine,
|
|
688
|
+
endLine,
|
|
689
|
+
similarity: r.similarity,
|
|
690
|
+
...content ? { content } : {}
|
|
691
|
+
};
|
|
692
|
+
});
|
|
693
|
+
const { results: finalResults, contentPagination } = applyContentPagination(mappedResults, args.includeContent);
|
|
694
|
+
return {
|
|
695
|
+
content: [
|
|
696
|
+
{
|
|
697
|
+
type: "text",
|
|
698
|
+
text: JSON.stringify(
|
|
699
|
+
{
|
|
700
|
+
query: args.query,
|
|
701
|
+
languages,
|
|
702
|
+
count: finalResults.length,
|
|
703
|
+
pagination: paginatedResult.pagination,
|
|
704
|
+
...contentPagination ? { contentPagination } : {},
|
|
705
|
+
results: finalResults
|
|
706
|
+
},
|
|
707
|
+
null,
|
|
708
|
+
2
|
|
709
|
+
)
|
|
710
|
+
}
|
|
711
|
+
]
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
};
|
|
715
|
+
var PatternSearchSchema = z.object({
|
|
716
|
+
pattern: z.string(),
|
|
717
|
+
projectPath: projectPathParam,
|
|
718
|
+
mode: z.enum(["entity", "content", "semantic", "hybrid"]).optional().default("hybrid"),
|
|
719
|
+
entityTypes: z.array(z.string()).optional(),
|
|
720
|
+
offset: z.number().optional().default(0),
|
|
721
|
+
limit: z.number().optional().default(SAFE_LIMITS.searchResults),
|
|
722
|
+
minSimilarity: z.number().optional().default(0.7),
|
|
723
|
+
// History filters (Prolly Tree)
|
|
724
|
+
changedInLastCommits: z.number().optional().describe("Filter: only entities changed in last N graph commits (Prolly Tree)"),
|
|
725
|
+
changedSinceMs: z.number().optional().describe("Filter: only entities changed since this Unix timestamp (ms)")
|
|
726
|
+
});
|
|
727
|
+
var PatternSearchToolHandler = class extends BaseToolHandler {
|
|
728
|
+
parseArgs(args) {
|
|
729
|
+
return PatternSearchSchema.parse(args);
|
|
730
|
+
}
|
|
731
|
+
async execute(args) {
|
|
732
|
+
const { PatternSearch } = await import('./pattern-search-WRBKEWYE.js');
|
|
733
|
+
const resolvedPath = this.resolveProjectPath(args);
|
|
734
|
+
const storage = await this.ensureGraphStorageForProject(resolvedPath);
|
|
735
|
+
const safeLimit = Math.min(args.limit, MAX_PAGE_SIZE);
|
|
736
|
+
let vectorStore = null;
|
|
737
|
+
let embeddingError = null;
|
|
738
|
+
try {
|
|
739
|
+
const semanticAgent = await this.ensureSemanticAgentForProject(resolvedPath);
|
|
740
|
+
embeddingError = semanticAgent.getEmbeddingInitError();
|
|
741
|
+
vectorStore = semanticAgent.getVectorStore?.();
|
|
742
|
+
} catch {
|
|
743
|
+
}
|
|
744
|
+
if ((args.mode === "semantic" || args.mode === "hybrid") && embeddingError) {
|
|
745
|
+
return {
|
|
746
|
+
content: [
|
|
747
|
+
{
|
|
748
|
+
type: "text",
|
|
749
|
+
text: JSON.stringify(
|
|
750
|
+
{
|
|
751
|
+
success: false,
|
|
752
|
+
error: `Embedding provider initialization failed: ${embeddingError.message}`,
|
|
753
|
+
hint: "Check if the configured embedding provider is available. Use mode='entity' or 'content' for text-based search."
|
|
754
|
+
},
|
|
755
|
+
null,
|
|
756
|
+
2
|
|
757
|
+
)
|
|
758
|
+
}
|
|
759
|
+
]
|
|
760
|
+
};
|
|
761
|
+
}
|
|
762
|
+
const patternSearch = new PatternSearch(storage, vectorStore, null);
|
|
763
|
+
await patternSearch.initialize();
|
|
764
|
+
let allResults = await patternSearch.search({
|
|
765
|
+
pattern: args.pattern,
|
|
766
|
+
mode: args.mode,
|
|
767
|
+
scope: { entityTypes: args.entityTypes },
|
|
768
|
+
limit: 500
|
|
769
|
+
});
|
|
770
|
+
if (args.changedInLastCommits !== void 0 || args.changedSinceMs !== void 0) {
|
|
771
|
+
const { getRecentlyChangedEntities } = await import('./recently-changed-FX5QR4Z2.js');
|
|
772
|
+
const adapter = storage.getLibSQLAdapter?.();
|
|
773
|
+
if (adapter) {
|
|
774
|
+
const recentlyChanged = await getRecentlyChangedEntities(adapter, {
|
|
775
|
+
lastCommits: args.changedInLastCommits,
|
|
776
|
+
sinceTimestamp: args.changedSinceMs
|
|
777
|
+
});
|
|
778
|
+
if (recentlyChanged) {
|
|
779
|
+
allResults = allResults.filter((r) => recentlyChanged.changedIds.has(r.entity.id));
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
const paginatedResult = paginate(allResults, args.offset, safeLimit);
|
|
784
|
+
return {
|
|
785
|
+
content: [
|
|
786
|
+
{
|
|
787
|
+
type: "text",
|
|
788
|
+
text: JSON.stringify(
|
|
789
|
+
{
|
|
790
|
+
pattern: args.pattern,
|
|
791
|
+
mode: args.mode,
|
|
792
|
+
count: paginatedResult.data.length,
|
|
793
|
+
pagination: paginatedResult.pagination,
|
|
794
|
+
results: paginatedResult.data.map((r) => ({
|
|
795
|
+
id: r.entity.id,
|
|
796
|
+
name: r.entity.name,
|
|
797
|
+
type: r.entity.type,
|
|
798
|
+
matchType: r.matchType,
|
|
799
|
+
score: r.score,
|
|
800
|
+
filePath: r.entity.filePath,
|
|
801
|
+
startLine: r.entity.location?.start?.line,
|
|
802
|
+
endLine: r.entity.location?.end?.line,
|
|
803
|
+
snippet: r.snippet
|
|
804
|
+
}))
|
|
805
|
+
},
|
|
806
|
+
null,
|
|
807
|
+
2
|
|
808
|
+
)
|
|
809
|
+
}
|
|
810
|
+
]
|
|
811
|
+
};
|
|
812
|
+
}
|
|
813
|
+
};
|
|
814
|
+
|
|
815
|
+
export { CrossLanguageSearchToolHandler, DetectCodeClonesToolHandler, FindSimilarCodeToolHandler, JscpdDetectClonesToolHandler, PatternSearchToolHandler, SemanticSearchToolHandler };
|
|
816
|
+
//# sourceMappingURL=semantic-tool-handlers-MYZPEUD2.js.map
|
|
817
|
+
//# sourceMappingURL=semantic-tool-handlers-MYZPEUD2.js.map
|