neuronlayer 0.1.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/CONTRIBUTING.md +127 -0
- package/LICENSE +21 -0
- package/README.md +305 -0
- package/dist/index.js +38016 -0
- package/esbuild.config.js +26 -0
- package/package.json +63 -0
- package/src/cli/commands.ts +382 -0
- package/src/core/adr-exporter.ts +253 -0
- package/src/core/architecture/architecture-enforcement.ts +228 -0
- package/src/core/architecture/duplicate-detector.ts +288 -0
- package/src/core/architecture/index.ts +6 -0
- package/src/core/architecture/pattern-learner.ts +306 -0
- package/src/core/architecture/pattern-library.ts +403 -0
- package/src/core/architecture/pattern-validator.ts +324 -0
- package/src/core/change-intelligence/bug-correlator.ts +444 -0
- package/src/core/change-intelligence/change-intelligence.ts +221 -0
- package/src/core/change-intelligence/change-tracker.ts +334 -0
- package/src/core/change-intelligence/fix-suggester.ts +340 -0
- package/src/core/change-intelligence/index.ts +5 -0
- package/src/core/code-verifier.ts +843 -0
- package/src/core/confidence/confidence-scorer.ts +251 -0
- package/src/core/confidence/conflict-checker.ts +289 -0
- package/src/core/confidence/index.ts +5 -0
- package/src/core/confidence/source-tracker.ts +263 -0
- package/src/core/confidence/warning-detector.ts +241 -0
- package/src/core/context-rot/compaction.ts +284 -0
- package/src/core/context-rot/context-health.ts +243 -0
- package/src/core/context-rot/context-rot-prevention.ts +213 -0
- package/src/core/context-rot/critical-context.ts +221 -0
- package/src/core/context-rot/drift-detector.ts +255 -0
- package/src/core/context-rot/index.ts +7 -0
- package/src/core/context.ts +263 -0
- package/src/core/decision-extractor.ts +339 -0
- package/src/core/decisions.ts +69 -0
- package/src/core/deja-vu.ts +421 -0
- package/src/core/engine.ts +1455 -0
- package/src/core/feature-context.ts +726 -0
- package/src/core/ghost-mode.ts +412 -0
- package/src/core/learning.ts +485 -0
- package/src/core/living-docs/activity-tracker.ts +296 -0
- package/src/core/living-docs/architecture-generator.ts +428 -0
- package/src/core/living-docs/changelog-generator.ts +348 -0
- package/src/core/living-docs/component-generator.ts +230 -0
- package/src/core/living-docs/doc-engine.ts +110 -0
- package/src/core/living-docs/doc-validator.ts +282 -0
- package/src/core/living-docs/index.ts +8 -0
- package/src/core/project-manager.ts +297 -0
- package/src/core/summarizer.ts +267 -0
- package/src/core/test-awareness/change-validator.ts +499 -0
- package/src/core/test-awareness/index.ts +5 -0
- package/src/index.ts +49 -0
- package/src/indexing/ast.ts +563 -0
- package/src/indexing/embeddings.ts +85 -0
- package/src/indexing/indexer.ts +245 -0
- package/src/indexing/watcher.ts +78 -0
- package/src/server/gateways/aggregator.ts +374 -0
- package/src/server/gateways/index.ts +473 -0
- package/src/server/gateways/memory-ghost.ts +343 -0
- package/src/server/gateways/memory-query.ts +452 -0
- package/src/server/gateways/memory-record.ts +346 -0
- package/src/server/gateways/memory-review.ts +410 -0
- package/src/server/gateways/memory-status.ts +517 -0
- package/src/server/gateways/memory-verify.ts +392 -0
- package/src/server/gateways/router.ts +434 -0
- package/src/server/gateways/types.ts +610 -0
- package/src/server/mcp.ts +154 -0
- package/src/server/resources.ts +85 -0
- package/src/server/tools.ts +2261 -0
- package/src/storage/database.ts +262 -0
- package/src/storage/tier1.ts +135 -0
- package/src/storage/tier2.ts +764 -0
- package/src/storage/tier3.ts +123 -0
- package/src/types/documentation.ts +619 -0
- package/src/types/index.ts +222 -0
- package/src/utils/config.ts +193 -0
- package/src/utils/files.ts +117 -0
- package/src/utils/time.ts +37 -0
- package/src/utils/tokens.ts +52 -0
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory Query Gateway
|
|
3
|
+
*
|
|
4
|
+
* Routes to: get_context, search_codebase, get_file_context, get_file_summary,
|
|
5
|
+
* get_symbol, get_dependencies, get_predicted_files, get_confidence,
|
|
6
|
+
* list_sources, suggest_existing
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { MemoryLayerEngine } from '../../core/engine.js';
|
|
10
|
+
import type { MemoryQueryInput, MemoryQueryResponse, MemoryQueryAction } from './types.js';
|
|
11
|
+
import { detectQueryAction, parseQuery, isFilePath } from './router.js';
|
|
12
|
+
import { aggregateQueryResults, mergeSearchResults } from './aggregator.js';
|
|
13
|
+
import { formatTimeAgo } from '../../utils/time.js';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Handle a memory_query gateway call
|
|
17
|
+
*/
|
|
18
|
+
export async function handleMemoryQuery(
|
|
19
|
+
engine: MemoryLayerEngine,
|
|
20
|
+
input: MemoryQueryInput
|
|
21
|
+
): Promise<MemoryQueryResponse> {
|
|
22
|
+
const action = detectQueryAction(input);
|
|
23
|
+
const sourcesUsed: string[] = [];
|
|
24
|
+
|
|
25
|
+
// Route based on detected/explicit action
|
|
26
|
+
switch (action) {
|
|
27
|
+
case 'file':
|
|
28
|
+
return handleFileQuery(engine, input, sourcesUsed);
|
|
29
|
+
|
|
30
|
+
case 'summary':
|
|
31
|
+
return handleSummaryQuery(engine, input, sourcesUsed);
|
|
32
|
+
|
|
33
|
+
case 'symbol':
|
|
34
|
+
return handleSymbolQuery(engine, input, sourcesUsed);
|
|
35
|
+
|
|
36
|
+
case 'dependencies':
|
|
37
|
+
return handleDependenciesQuery(engine, input, sourcesUsed);
|
|
38
|
+
|
|
39
|
+
case 'predict':
|
|
40
|
+
return handlePredictQuery(engine, input, sourcesUsed);
|
|
41
|
+
|
|
42
|
+
case 'confidence':
|
|
43
|
+
return handleConfidenceQuery(engine, input, sourcesUsed);
|
|
44
|
+
|
|
45
|
+
case 'sources':
|
|
46
|
+
return handleSourcesQuery(engine, input, sourcesUsed);
|
|
47
|
+
|
|
48
|
+
case 'existing':
|
|
49
|
+
return handleExistingQuery(engine, input, sourcesUsed);
|
|
50
|
+
|
|
51
|
+
case 'search':
|
|
52
|
+
return handleSearchOnlyQuery(engine, input, sourcesUsed);
|
|
53
|
+
|
|
54
|
+
case 'context':
|
|
55
|
+
default:
|
|
56
|
+
return handleContextQuery(engine, input, sourcesUsed);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Combined context + search query (default behavior)
|
|
62
|
+
* Enhanced with déjà vu detection and proactive predictions
|
|
63
|
+
*/
|
|
64
|
+
async function handleContextQuery(
|
|
65
|
+
engine: MemoryLayerEngine,
|
|
66
|
+
input: MemoryQueryInput,
|
|
67
|
+
sourcesUsed: string[]
|
|
68
|
+
): Promise<MemoryQueryResponse> {
|
|
69
|
+
sourcesUsed.push('get_context', 'search_codebase');
|
|
70
|
+
|
|
71
|
+
// Notify ghost mode of file access for silent tracking
|
|
72
|
+
if (input.file) {
|
|
73
|
+
engine.notifyFileAccess(input.file).catch(err => {
|
|
74
|
+
console.error('Ghost mode file access error:', err);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Run context, search, and déjà vu in parallel
|
|
79
|
+
const [contextResult, searchResults, dejaVuMatches] = await Promise.all([
|
|
80
|
+
engine.getContext(input.query, input.file, input.max_tokens),
|
|
81
|
+
engine.searchCodebase(input.query, input.max_results || 10),
|
|
82
|
+
engine.findDejaVu(input.query, 3), // Check for similar past problems
|
|
83
|
+
]);
|
|
84
|
+
|
|
85
|
+
const response = aggregateQueryResults(
|
|
86
|
+
contextResult,
|
|
87
|
+
searchResults,
|
|
88
|
+
sourcesUsed
|
|
89
|
+
) as MemoryQueryResponse;
|
|
90
|
+
|
|
91
|
+
// Add déjà vu matches if found (proactive intelligence)
|
|
92
|
+
// Surfaced prominently to address "I feel like I solved this before" problem
|
|
93
|
+
if (dejaVuMatches.length > 0) {
|
|
94
|
+
sourcesUsed.push('deja_vu');
|
|
95
|
+
|
|
96
|
+
// Format user-friendly messages
|
|
97
|
+
const formattedMatches = dejaVuMatches.map(m => ({
|
|
98
|
+
type: m.type,
|
|
99
|
+
message: m.message,
|
|
100
|
+
file: m.file,
|
|
101
|
+
similarity: m.similarity,
|
|
102
|
+
when: m.when.toISOString(),
|
|
103
|
+
context: m.context,
|
|
104
|
+
// Human-readable time ago
|
|
105
|
+
time_ago: formatTimeAgo(m.when),
|
|
106
|
+
}));
|
|
107
|
+
|
|
108
|
+
(response as MemoryQueryResponse & { deja_vu?: unknown }).deja_vu = {
|
|
109
|
+
has_matches: true,
|
|
110
|
+
hint: formattedMatches.length === 1
|
|
111
|
+
? `You worked on something similar ${formattedMatches[0]?.time_ago || 'recently'}`
|
|
112
|
+
: `Found ${formattedMatches.length} similar past problems`,
|
|
113
|
+
matches: formattedMatches,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Add predicted files (proactive context)
|
|
118
|
+
if (input.file) {
|
|
119
|
+
sourcesUsed.push('predict_files');
|
|
120
|
+
const predictedFiles = engine.getPredictedFiles(input.file, input.query);
|
|
121
|
+
if (predictedFiles.length > 0) {
|
|
122
|
+
(response as MemoryQueryResponse & { predictions?: unknown }).predictions = {
|
|
123
|
+
likely_next_files: predictedFiles.slice(0, 5),
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// If confidence requested, add it
|
|
129
|
+
if (input.include_confidence && input.code) {
|
|
130
|
+
sourcesUsed.push('get_confidence');
|
|
131
|
+
const confidence = await engine.getConfidence(input.code, input.query);
|
|
132
|
+
response.confidence = {
|
|
133
|
+
level: confidence.confidence,
|
|
134
|
+
score: confidence.score,
|
|
135
|
+
reasoning: confidence.reasoning,
|
|
136
|
+
indicator: engine.getConfidenceIndicator(confidence.confidence),
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Record query for future déjà vu detection
|
|
141
|
+
engine.recordQueryForDejaVu(input.query, contextResult.sources);
|
|
142
|
+
|
|
143
|
+
return response;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Search only (no context assembly)
|
|
148
|
+
*/
|
|
149
|
+
async function handleSearchOnlyQuery(
|
|
150
|
+
engine: MemoryLayerEngine,
|
|
151
|
+
input: MemoryQueryInput,
|
|
152
|
+
sourcesUsed: string[]
|
|
153
|
+
): Promise<MemoryQueryResponse> {
|
|
154
|
+
sourcesUsed.push('search_codebase');
|
|
155
|
+
|
|
156
|
+
const searchResults = await engine.searchCodebase(
|
|
157
|
+
input.query,
|
|
158
|
+
input.max_results || 10
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
return {
|
|
162
|
+
sources_used: sourcesUsed,
|
|
163
|
+
search_results: searchResults.map(r => ({
|
|
164
|
+
file: r.file,
|
|
165
|
+
preview: r.preview,
|
|
166
|
+
relevance: r.similarity,
|
|
167
|
+
line_start: r.lineStart,
|
|
168
|
+
line_end: r.lineEnd,
|
|
169
|
+
})),
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* File context retrieval
|
|
175
|
+
*/
|
|
176
|
+
async function handleFileQuery(
|
|
177
|
+
engine: MemoryLayerEngine,
|
|
178
|
+
input: MemoryQueryInput,
|
|
179
|
+
sourcesUsed: string[]
|
|
180
|
+
): Promise<MemoryQueryResponse> {
|
|
181
|
+
sourcesUsed.push('get_file_context');
|
|
182
|
+
|
|
183
|
+
// Determine file path from input.file or input.query
|
|
184
|
+
const filePath = input.file || (isFilePath(input.query) ? input.query : null);
|
|
185
|
+
|
|
186
|
+
if (!filePath) {
|
|
187
|
+
return {
|
|
188
|
+
sources_used: sourcesUsed,
|
|
189
|
+
file_content: undefined,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const result = await engine.getFileContext(filePath);
|
|
194
|
+
|
|
195
|
+
if (!result) {
|
|
196
|
+
return {
|
|
197
|
+
sources_used: sourcesUsed,
|
|
198
|
+
file_content: undefined,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return {
|
|
203
|
+
sources_used: sourcesUsed,
|
|
204
|
+
file_content: {
|
|
205
|
+
path: filePath,
|
|
206
|
+
content: result.content,
|
|
207
|
+
language: result.language,
|
|
208
|
+
lines: result.lines,
|
|
209
|
+
},
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* File summary retrieval
|
|
215
|
+
*/
|
|
216
|
+
async function handleSummaryQuery(
|
|
217
|
+
engine: MemoryLayerEngine,
|
|
218
|
+
input: MemoryQueryInput,
|
|
219
|
+
sourcesUsed: string[]
|
|
220
|
+
): Promise<MemoryQueryResponse> {
|
|
221
|
+
sourcesUsed.push('get_file_summary');
|
|
222
|
+
|
|
223
|
+
const filePath = input.file || (isFilePath(input.query) ? input.query : null);
|
|
224
|
+
|
|
225
|
+
if (!filePath) {
|
|
226
|
+
return {
|
|
227
|
+
sources_used: sourcesUsed,
|
|
228
|
+
file_summary: undefined,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const summary = engine.getFileSummary(filePath);
|
|
233
|
+
|
|
234
|
+
return {
|
|
235
|
+
sources_used: sourcesUsed,
|
|
236
|
+
file_summary: summary ? {
|
|
237
|
+
path: filePath,
|
|
238
|
+
summary,
|
|
239
|
+
} : undefined,
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Symbol lookup
|
|
245
|
+
*/
|
|
246
|
+
async function handleSymbolQuery(
|
|
247
|
+
engine: MemoryLayerEngine,
|
|
248
|
+
input: MemoryQueryInput,
|
|
249
|
+
sourcesUsed: string[]
|
|
250
|
+
): Promise<MemoryQueryResponse> {
|
|
251
|
+
sourcesUsed.push('get_symbol');
|
|
252
|
+
|
|
253
|
+
const symbolName = input.symbol || input.query;
|
|
254
|
+
const results = await engine.searchSymbols(
|
|
255
|
+
symbolName,
|
|
256
|
+
input.symbol_kind,
|
|
257
|
+
input.max_results || 10
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
// If we have results and a specific file, also get dependencies
|
|
261
|
+
const firstResult = results[0];
|
|
262
|
+
if (results.length > 0 && firstResult && firstResult.filePath) {
|
|
263
|
+
sourcesUsed.push('get_dependencies');
|
|
264
|
+
const deps = engine.getFileDependencies(firstResult.filePath);
|
|
265
|
+
|
|
266
|
+
return {
|
|
267
|
+
sources_used: sourcesUsed,
|
|
268
|
+
symbols: results.map(s => ({
|
|
269
|
+
name: s.name,
|
|
270
|
+
kind: s.kind,
|
|
271
|
+
file: s.filePath,
|
|
272
|
+
line_start: s.lineStart,
|
|
273
|
+
line_end: s.lineEnd,
|
|
274
|
+
signature: s.signature || undefined,
|
|
275
|
+
exported: s.exported,
|
|
276
|
+
})),
|
|
277
|
+
dependencies: {
|
|
278
|
+
file: firstResult.filePath,
|
|
279
|
+
imports: deps.imports,
|
|
280
|
+
imported_by: deps.importedBy,
|
|
281
|
+
symbols: deps.symbols,
|
|
282
|
+
},
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
return {
|
|
287
|
+
sources_used: sourcesUsed,
|
|
288
|
+
symbols: results.map(s => ({
|
|
289
|
+
name: s.name,
|
|
290
|
+
kind: s.kind,
|
|
291
|
+
file: s.filePath,
|
|
292
|
+
line_start: s.lineStart,
|
|
293
|
+
line_end: s.lineEnd,
|
|
294
|
+
signature: s.signature || undefined,
|
|
295
|
+
exported: s.exported,
|
|
296
|
+
})),
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Dependency lookup
|
|
302
|
+
*/
|
|
303
|
+
async function handleDependenciesQuery(
|
|
304
|
+
engine: MemoryLayerEngine,
|
|
305
|
+
input: MemoryQueryInput,
|
|
306
|
+
sourcesUsed: string[]
|
|
307
|
+
): Promise<MemoryQueryResponse> {
|
|
308
|
+
sourcesUsed.push('get_dependencies');
|
|
309
|
+
|
|
310
|
+
const filePath = input.file || (isFilePath(input.query) ? input.query : null);
|
|
311
|
+
|
|
312
|
+
if (!filePath) {
|
|
313
|
+
return {
|
|
314
|
+
sources_used: sourcesUsed,
|
|
315
|
+
dependencies: undefined,
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const deps = engine.getFileDependencies(filePath);
|
|
320
|
+
|
|
321
|
+
return {
|
|
322
|
+
sources_used: sourcesUsed,
|
|
323
|
+
dependencies: {
|
|
324
|
+
file: filePath,
|
|
325
|
+
imports: deps.imports,
|
|
326
|
+
imported_by: deps.importedBy,
|
|
327
|
+
symbols: deps.symbols,
|
|
328
|
+
},
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Predicted files query
|
|
334
|
+
*/
|
|
335
|
+
async function handlePredictQuery(
|
|
336
|
+
engine: MemoryLayerEngine,
|
|
337
|
+
input: MemoryQueryInput,
|
|
338
|
+
sourcesUsed: string[]
|
|
339
|
+
): Promise<MemoryQueryResponse> {
|
|
340
|
+
sourcesUsed.push('get_predicted_files');
|
|
341
|
+
|
|
342
|
+
if (!input.file) {
|
|
343
|
+
return {
|
|
344
|
+
sources_used: sourcesUsed,
|
|
345
|
+
predicted_files: undefined,
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
const predicted = engine.getPredictedFiles(input.file, input.query);
|
|
350
|
+
const preFetched = await engine.preFetchFiles(input.file, input.query);
|
|
351
|
+
|
|
352
|
+
return {
|
|
353
|
+
sources_used: sourcesUsed,
|
|
354
|
+
predicted_files: {
|
|
355
|
+
files: predicted,
|
|
356
|
+
pre_fetched: preFetched,
|
|
357
|
+
},
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Confidence assessment query
|
|
363
|
+
*/
|
|
364
|
+
async function handleConfidenceQuery(
|
|
365
|
+
engine: MemoryLayerEngine,
|
|
366
|
+
input: MemoryQueryInput,
|
|
367
|
+
sourcesUsed: string[]
|
|
368
|
+
): Promise<MemoryQueryResponse> {
|
|
369
|
+
sourcesUsed.push('get_confidence');
|
|
370
|
+
|
|
371
|
+
if (!input.code) {
|
|
372
|
+
return {
|
|
373
|
+
sources_used: sourcesUsed,
|
|
374
|
+
confidence: undefined,
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
const result = await engine.getConfidence(input.code, input.query);
|
|
379
|
+
|
|
380
|
+
return {
|
|
381
|
+
sources_used: sourcesUsed,
|
|
382
|
+
confidence: {
|
|
383
|
+
level: result.confidence,
|
|
384
|
+
score: result.score,
|
|
385
|
+
reasoning: result.reasoning,
|
|
386
|
+
indicator: engine.getConfidenceIndicator(result.confidence),
|
|
387
|
+
},
|
|
388
|
+
source_attribution: {
|
|
389
|
+
codebase_matches: result.sources.codebase.length,
|
|
390
|
+
decision_matches: result.sources.decisions.length,
|
|
391
|
+
pattern_matches: result.sources.patterns.length,
|
|
392
|
+
used_general_knowledge: result.sources.usedGeneralKnowledge,
|
|
393
|
+
},
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Source attribution query
|
|
399
|
+
*/
|
|
400
|
+
async function handleSourcesQuery(
|
|
401
|
+
engine: MemoryLayerEngine,
|
|
402
|
+
input: MemoryQueryInput,
|
|
403
|
+
sourcesUsed: string[]
|
|
404
|
+
): Promise<MemoryQueryResponse> {
|
|
405
|
+
sourcesUsed.push('list_sources');
|
|
406
|
+
|
|
407
|
+
if (!input.code) {
|
|
408
|
+
return {
|
|
409
|
+
sources_used: sourcesUsed,
|
|
410
|
+
source_attribution: undefined,
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
const sources = await engine.listConfidenceSources(input.code, input.query, true);
|
|
415
|
+
|
|
416
|
+
return {
|
|
417
|
+
sources_used: sourcesUsed,
|
|
418
|
+
source_attribution: {
|
|
419
|
+
codebase_matches: sources.codebase.length,
|
|
420
|
+
decision_matches: sources.decisions.length,
|
|
421
|
+
pattern_matches: sources.patterns.length,
|
|
422
|
+
used_general_knowledge: sources.usedGeneralKnowledge,
|
|
423
|
+
},
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Existing function suggestions query
|
|
429
|
+
*/
|
|
430
|
+
async function handleExistingQuery(
|
|
431
|
+
engine: MemoryLayerEngine,
|
|
432
|
+
input: MemoryQueryInput,
|
|
433
|
+
sourcesUsed: string[]
|
|
434
|
+
): Promise<MemoryQueryResponse> {
|
|
435
|
+
sourcesUsed.push('suggest_existing');
|
|
436
|
+
|
|
437
|
+
const suggestions = engine.suggestExisting(
|
|
438
|
+
input.query,
|
|
439
|
+
input.max_results || 5
|
|
440
|
+
);
|
|
441
|
+
|
|
442
|
+
return {
|
|
443
|
+
sources_used: sourcesUsed,
|
|
444
|
+
existing_functions: suggestions.map(s => ({
|
|
445
|
+
name: s.name,
|
|
446
|
+
file: s.file,
|
|
447
|
+
line: s.line,
|
|
448
|
+
signature: s.signature,
|
|
449
|
+
similarity: s.similarity,
|
|
450
|
+
})),
|
|
451
|
+
};
|
|
452
|
+
}
|