@phmotad/fire-code 0.2.8 → 0.2.9
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/cli/commands/index-cmd.d.ts +1 -0
- package/dist/cli/commands/index-cmd.d.ts.map +1 -1
- package/dist/cli/commands/index-cmd.js +83 -14
- package/dist/cli/commands/index-cmd.js.map +1 -1
- package/dist/core/ExecutionEngine.d.ts +3 -1
- package/dist/core/ExecutionEngine.d.ts.map +1 -1
- package/dist/core/ExecutionEngine.js +36 -17
- package/dist/core/ExecutionEngine.js.map +1 -1
- package/dist/db/DatabaseManager.d.ts +4 -0
- package/dist/db/DatabaseManager.d.ts.map +1 -1
- package/dist/db/DatabaseManager.js +13 -0
- package/dist/db/DatabaseManager.js.map +1 -1
- package/dist/db/schema.d.ts +1 -1
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/schema.js +20 -0
- package/dist/db/schema.js.map +1 -1
- package/dist/git/GitManager.d.ts +10 -0
- package/dist/git/GitManager.d.ts.map +1 -1
- package/dist/git/GitManager.js +46 -0
- package/dist/git/GitManager.js.map +1 -1
- package/dist/graph/GraphStore.d.ts +6 -1
- package/dist/graph/GraphStore.d.ts.map +1 -1
- package/dist/graph/InMemoryGraphStore.d.ts +1 -0
- package/dist/graph/InMemoryGraphStore.d.ts.map +1 -1
- package/dist/graph/InMemoryGraphStore.js +13 -2
- package/dist/graph/InMemoryGraphStore.js.map +1 -1
- package/dist/graph/SQLiteGraphStore.d.ts.map +1 -1
- package/dist/graph/SQLiteGraphStore.js +8 -2
- package/dist/graph/SQLiteGraphStore.js.map +1 -1
- package/dist/indexing/ASTParser.d.ts +1 -1
- package/dist/indexing/ASTParser.d.ts.map +1 -1
- package/dist/indexing/ASTParser.js +7 -1
- package/dist/indexing/ASTParser.js.map +1 -1
- package/dist/indexing/EmbeddingGenerator.d.ts.map +1 -1
- package/dist/indexing/EmbeddingGenerator.js +2 -25
- package/dist/indexing/EmbeddingGenerator.js.map +1 -1
- package/dist/indexing/FileScanner.d.ts.map +1 -1
- package/dist/indexing/FileScanner.js +2 -1
- package/dist/indexing/FileScanner.js.map +1 -1
- package/dist/indexing/GitIndexer.d.ts +4 -0
- package/dist/indexing/GitIndexer.d.ts.map +1 -0
- package/dist/indexing/GitIndexer.js +59 -0
- package/dist/indexing/GitIndexer.js.map +1 -0
- package/dist/indexing/GraphBuilder.d.ts.map +1 -1
- package/dist/indexing/GraphBuilder.js +21 -1
- package/dist/indexing/GraphBuilder.js.map +1 -1
- package/dist/indexing/Indexer.d.ts +3 -2
- package/dist/indexing/Indexer.d.ts.map +1 -1
- package/dist/indexing/Indexer.js +25 -6
- package/dist/indexing/Indexer.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +20 -7
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools/execute.d.ts +3 -0
- package/dist/mcp/tools/execute.d.ts.map +1 -1
- package/dist/mcp/tools/execute.js +2 -0
- package/dist/mcp/tools/execute.js.map +1 -1
- package/dist/mcp/tools/find_similar.d.ts +17 -0
- package/dist/mcp/tools/find_similar.d.ts.map +1 -0
- package/dist/mcp/tools/find_similar.js +95 -0
- package/dist/mcp/tools/find_similar.js.map +1 -0
- package/dist/mcp/tools/get_context.d.ts +3 -0
- package/dist/mcp/tools/get_context.d.ts.map +1 -1
- package/dist/mcp/tools/get_context.js +68 -7
- package/dist/mcp/tools/get_context.js.map +1 -1
- package/dist/mcp/tools/search_code.d.ts.map +1 -1
- package/dist/mcp/tools/search_code.js +22 -4
- package/dist/mcp/tools/search_code.js.map +1 -1
- package/dist/mcp/tools/smart_search.d.ts.map +1 -1
- package/dist/mcp/tools/smart_search.js +122 -29
- package/dist/mcp/tools/smart_search.js.map +1 -1
- package/dist/memory/HybridMemory.d.ts +4 -0
- package/dist/memory/HybridMemory.d.ts.map +1 -1
- package/dist/memory/HybridMemory.js +120 -29
- package/dist/memory/HybridMemory.js.map +1 -1
- package/dist/utils/modelManager.d.ts +37 -0
- package/dist/utils/modelManager.d.ts.map +1 -0
- package/dist/utils/modelManager.js +90 -0
- package/dist/utils/modelManager.js.map +1 -0
- package/dist/utils/workerPool.d.ts +8 -0
- package/dist/utils/workerPool.d.ts.map +1 -0
- package/dist/utils/workerPool.js +75 -0
- package/dist/utils/workerPool.js.map +1 -0
- package/dist/vector/MemoryVectorStore.d.ts.map +1 -1
- package/dist/vector/MemoryVectorStore.js +19 -13
- package/dist/vector/MemoryVectorStore.js.map +1 -1
- package/dist/vector/SQLiteVectorStore.d.ts +13 -0
- package/dist/vector/SQLiteVectorStore.d.ts.map +1 -0
- package/dist/vector/SQLiteVectorStore.js +111 -0
- package/dist/vector/SQLiteVectorStore.js.map +1 -0
- package/dist/vector/VectorStore.d.ts +0 -1
- package/dist/vector/VectorStore.d.ts.map +1 -1
- package/dist/workers/embeddingWorker.d.ts +2 -0
- package/dist/workers/embeddingWorker.d.ts.map +1 -0
- package/dist/workers/embeddingWorker.js +42 -0
- package/dist/workers/embeddingWorker.js.map +1 -0
- package/package.json +3 -1
|
@@ -5,7 +5,8 @@ exports.smartSearchTool = smartSearchTool;
|
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
6
|
const path_1 = require("path");
|
|
7
7
|
const fs_1 = require("fs");
|
|
8
|
-
const
|
|
8
|
+
const DatabaseManager_js_1 = require("../../db/DatabaseManager.js");
|
|
9
|
+
const paths_js_1 = require("../../utils/paths.js");
|
|
9
10
|
exports.SmartSearchInputSchema = zod_1.z.object({
|
|
10
11
|
query: zod_1.z.string().describe('Search term — matches symbol names, file names, and content'),
|
|
11
12
|
path: zod_1.z.string().optional().describe('Root directory to search (default: cwd)'),
|
|
@@ -14,6 +15,15 @@ exports.SmartSearchInputSchema = zod_1.z.object({
|
|
|
14
15
|
});
|
|
15
16
|
const SKIP_DIRS = new Set(['node_modules', '.git', 'dist', 'build', '.firecode', 'coverage', '.next']);
|
|
16
17
|
const CODE_EXTS = new Set(['.ts', '.tsx', '.js', '.jsx', '.mts', '.cts', '.py', '.go', '.rs', '.java', '.cs', '.rb', '.php', '.swift', '.kt', '.md']);
|
|
18
|
+
function getProjectName(rootDir) {
|
|
19
|
+
try {
|
|
20
|
+
const pkg = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(rootDir, 'package.json'), 'utf8'));
|
|
21
|
+
return pkg.name ?? (0, path_1.basename)(rootDir);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return (0, path_1.basename)(rootDir);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
17
27
|
function walkFiles(dir, filePattern) {
|
|
18
28
|
const files = [];
|
|
19
29
|
function walk(current) {
|
|
@@ -27,7 +37,7 @@ function walkFiles(dir, filePattern) {
|
|
|
27
37
|
for (const entry of entries) {
|
|
28
38
|
if (SKIP_DIRS.has(entry))
|
|
29
39
|
continue;
|
|
30
|
-
const full = (0,
|
|
40
|
+
const full = (0, path_1.join)(current, entry);
|
|
31
41
|
let stat;
|
|
32
42
|
try {
|
|
33
43
|
stat = (0, fs_1.statSync)(full);
|
|
@@ -38,7 +48,7 @@ function walkFiles(dir, filePattern) {
|
|
|
38
48
|
if (stat.isDirectory()) {
|
|
39
49
|
walk(full);
|
|
40
50
|
}
|
|
41
|
-
else if (CODE_EXTS.has((0,
|
|
51
|
+
else if (CODE_EXTS.has((0, path_1.extname)(entry))) {
|
|
42
52
|
if (!filePattern || full.includes(filePattern)) {
|
|
43
53
|
files.push(full);
|
|
44
54
|
}
|
|
@@ -48,35 +58,89 @@ function walkFiles(dir, filePattern) {
|
|
|
48
58
|
walk(dir);
|
|
49
59
|
return files;
|
|
50
60
|
}
|
|
51
|
-
function scoreMatch(line,
|
|
52
|
-
const lq =
|
|
61
|
+
function scoreMatch(line, queryToken) {
|
|
62
|
+
const lq = queryToken.toLowerCase();
|
|
53
63
|
const ll = line.toLowerCase();
|
|
54
|
-
// Exact symbol
|
|
64
|
+
// Exact symbol declaration
|
|
55
65
|
const symMatch = line.match(/(?:function|class|interface|type|const|let|var)\s+(\w+)/);
|
|
56
|
-
if (symMatch && symMatch[1].toLowerCase()
|
|
66
|
+
if (symMatch && symMatch[1].toLowerCase() === lq)
|
|
57
67
|
return 100;
|
|
68
|
+
if (symMatch && symMatch[1].toLowerCase().includes(lq))
|
|
69
|
+
return 80;
|
|
70
|
+
// Method declaration (handles class methods: ` methodName(`)
|
|
71
|
+
const methodMatch = line.match(/^\s+(?:async\s+|static\s+|private\s+|public\s+|protected\s+)*(\w+)\s*\(/);
|
|
72
|
+
if (methodMatch && methodMatch[1].toLowerCase() === lq)
|
|
73
|
+
return 90;
|
|
58
74
|
// Export match
|
|
59
75
|
if (line.includes('export') && ll.includes(lq))
|
|
60
|
-
return
|
|
76
|
+
return 70;
|
|
61
77
|
// Import match
|
|
62
78
|
if (line.includes('import') && ll.includes(lq))
|
|
63
|
-
return
|
|
79
|
+
return 50;
|
|
64
80
|
// General content
|
|
65
81
|
if (ll.includes(lq))
|
|
66
|
-
return
|
|
82
|
+
return 30;
|
|
67
83
|
return 0;
|
|
68
84
|
}
|
|
85
|
+
/** Query the indexed graph for exact symbol matches (fast, precise). */
|
|
86
|
+
function graphSymbolSearch(tokens, rootDir) {
|
|
87
|
+
const firedotDir = (0, paths_js_1.getFireCodeDir)(rootDir);
|
|
88
|
+
if (!(0, fs_1.existsSync)(firedotDir))
|
|
89
|
+
return [];
|
|
90
|
+
try {
|
|
91
|
+
const project = getProjectName(rootDir);
|
|
92
|
+
const db = DatabaseManager_js_1.DatabaseManager.getInstance(firedotDir);
|
|
93
|
+
const graphStore = db.getGraphStore(project);
|
|
94
|
+
const results = [];
|
|
95
|
+
for (const token of tokens) {
|
|
96
|
+
if (token.length < 2)
|
|
97
|
+
continue;
|
|
98
|
+
// Exact function/method match
|
|
99
|
+
const fnNodes = graphStore.query({ type: 'function', label: token, exact: true });
|
|
100
|
+
for (const node of fnNodes) {
|
|
101
|
+
const filePath = node.filePath.replace(/\\/g, '/');
|
|
102
|
+
const label = node.parentClass ? `${node.parentClass}.${node.label}` : node.label;
|
|
103
|
+
results.push({
|
|
104
|
+
file: filePath,
|
|
105
|
+
line: node.line,
|
|
106
|
+
kind: 'graph',
|
|
107
|
+
match: `${label}(${node.parameters.join(', ')})${node.returnType ? ': ' + node.returnType : ''}`,
|
|
108
|
+
context: `defined at L${node.line}${node.parentClass ? ` [class: ${node.parentClass}]` : ''}`,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
// Exact file name match
|
|
112
|
+
const fileNodes = graphStore.query({ type: 'file', label: token, exact: true });
|
|
113
|
+
for (const node of fileNodes) {
|
|
114
|
+
results.push({
|
|
115
|
+
file: (node.path ?? node.label).replace(/\\/g, '/'),
|
|
116
|
+
line: 0,
|
|
117
|
+
kind: 'graph',
|
|
118
|
+
match: node.label,
|
|
119
|
+
context: `file (exports: ${node.exports.slice(0, 4).join(', ')})`,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return results;
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
return [];
|
|
127
|
+
}
|
|
128
|
+
}
|
|
69
129
|
async function smartSearchTool(input, cwd) {
|
|
70
130
|
const rootDir = (0, path_1.resolve)(input.path ?? cwd);
|
|
71
131
|
if (!(0, fs_1.existsSync)(rootDir)) {
|
|
72
132
|
return JSON.stringify({ error: `Directory not found: ${rootDir}` });
|
|
73
133
|
}
|
|
74
|
-
|
|
75
|
-
const
|
|
76
|
-
const query = input.query.toLowerCase();
|
|
134
|
+
// Split query into individual tokens for multi-symbol queries
|
|
135
|
+
const tokens = input.query.split(/[\s,]+/).filter(t => t.length > 1);
|
|
77
136
|
const maxResults = input.max_results ?? 20;
|
|
137
|
+
// ── 1. Graph-based symbol lookup (highest precision) ─────────────────────
|
|
138
|
+
const graphResults = graphSymbolSearch(tokens, rootDir);
|
|
139
|
+
// ── 2. File scan (catches anything not yet indexed) ───────────────────────
|
|
140
|
+
const files = walkFiles(rootDir, input.file_pattern);
|
|
141
|
+
const fileResults = [];
|
|
78
142
|
for (const filePath of files) {
|
|
79
|
-
if (
|
|
143
|
+
if (fileResults.length >= maxResults * 4)
|
|
80
144
|
break;
|
|
81
145
|
let content;
|
|
82
146
|
try {
|
|
@@ -85,47 +149,76 @@ async function smartSearchTool(input, cwd) {
|
|
|
85
149
|
catch {
|
|
86
150
|
continue;
|
|
87
151
|
}
|
|
88
|
-
const relPath = (0,
|
|
89
|
-
// File name match
|
|
90
|
-
|
|
91
|
-
|
|
152
|
+
const relPath = (0, path_1.relative)(rootDir, filePath).replace(/\\/g, '/');
|
|
153
|
+
// File name match against any token
|
|
154
|
+
const fileNameLower = relPath.toLowerCase();
|
|
155
|
+
if (tokens.some(t => fileNameLower.includes(t.toLowerCase()))) {
|
|
156
|
+
fileResults.push({ file: relPath, line: 0, kind: 'symbol', match: relPath, context: `file: ${relPath}` });
|
|
92
157
|
}
|
|
93
158
|
const lines = content.split('\n');
|
|
94
159
|
for (let i = 0; i < lines.length; i++) {
|
|
95
|
-
|
|
96
|
-
|
|
160
|
+
// Score against each token, take highest
|
|
161
|
+
let bestScore = 0;
|
|
162
|
+
for (const token of tokens) {
|
|
163
|
+
const s = scoreMatch(lines[i], token);
|
|
164
|
+
if (s > bestScore)
|
|
165
|
+
bestScore = s;
|
|
166
|
+
}
|
|
167
|
+
if (bestScore > 0) {
|
|
97
168
|
const ctx = lines.slice(Math.max(0, i - 1), i + 2).join('\n');
|
|
98
|
-
|
|
169
|
+
fileResults.push({
|
|
99
170
|
file: relPath,
|
|
100
171
|
line: i + 1,
|
|
101
|
-
kind:
|
|
172
|
+
kind: bestScore >= 70 ? 'symbol' : 'content',
|
|
102
173
|
match: lines[i].trim().slice(0, 120),
|
|
103
174
|
context: ctx,
|
|
104
175
|
});
|
|
105
176
|
}
|
|
106
177
|
}
|
|
107
178
|
}
|
|
108
|
-
// Sort: symbols first, then by file name
|
|
109
|
-
|
|
179
|
+
// Sort file results: symbols first, then by file name
|
|
180
|
+
fileResults.sort((a, b) => {
|
|
110
181
|
if (a.kind !== b.kind)
|
|
111
182
|
return a.kind === 'symbol' ? -1 : 1;
|
|
112
183
|
return a.file.localeCompare(b.file);
|
|
113
184
|
});
|
|
114
|
-
|
|
185
|
+
// ── 3. Merge: graph results first (deduplicated by file+line) ────────────
|
|
186
|
+
const seen = new Set();
|
|
187
|
+
const merged = [];
|
|
188
|
+
for (const r of graphResults) {
|
|
189
|
+
const key = `${r.file}:${r.line}`;
|
|
190
|
+
if (!seen.has(key)) {
|
|
191
|
+
seen.add(key);
|
|
192
|
+
merged.push(r);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
for (const r of fileResults) {
|
|
196
|
+
const key = `${r.file}:${r.line}`;
|
|
197
|
+
if (!seen.has(key)) {
|
|
198
|
+
seen.add(key);
|
|
199
|
+
merged.push(r);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
const top = merged.slice(0, maxResults);
|
|
115
203
|
if (top.length === 0) {
|
|
116
204
|
return `No results for "${input.query}" in ${rootDir}`;
|
|
117
205
|
}
|
|
118
|
-
const
|
|
206
|
+
const outputLines = [
|
|
207
|
+
`# Search: "${input.query}" — ${top.length} results (${graphResults.length} from index, ${files.length} files scanned)\n`,
|
|
208
|
+
];
|
|
119
209
|
let lastFile = '';
|
|
120
210
|
for (const r of top) {
|
|
121
211
|
if (r.file !== lastFile) {
|
|
122
|
-
|
|
212
|
+
outputLines.push(`\n## ${r.file}`);
|
|
123
213
|
lastFile = r.file;
|
|
124
214
|
}
|
|
125
215
|
if (r.line > 0) {
|
|
126
|
-
|
|
216
|
+
outputLines.push(` L${r.line} [${r.kind}] ${r.match}`);
|
|
217
|
+
}
|
|
218
|
+
else if (r.kind === 'graph') {
|
|
219
|
+
outputLines.push(` [${r.kind}] ${r.match} — ${r.context}`);
|
|
127
220
|
}
|
|
128
221
|
}
|
|
129
|
-
return
|
|
222
|
+
return outputLines.join('\n');
|
|
130
223
|
}
|
|
131
224
|
//# sourceMappingURL=smart_search.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"smart_search.js","sourceRoot":"","sources":["../../../src/mcp/tools/smart_search.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"smart_search.js","sourceRoot":"","sources":["../../../src/mcp/tools/smart_search.ts"],"names":[],"mappings":";;;AAqIA,0CAgGC;AArOD,6BAAwB;AACxB,+BAAkE;AAClE,2BAAqE;AACrE,oEAA8D;AAC9D,mDAAsD;AAGzC,QAAA,sBAAsB,GAAG,OAAC,CAAC,MAAM,CAAC;IAC7C,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6DAA6D,CAAC;IACzF,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,yCAAyC,CAAC;IAC/E,WAAW,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,2BAA2B,CAAC;IACpF,YAAY,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4DAA4D,CAAC;CAC3G,CAAC,CAAC;AAIH,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;AACvG,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;AAUtJ,SAAS,cAAc,CAAC,OAAe;IACrC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAA,iBAAY,EAAC,IAAA,WAAI,EAAC,OAAO,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAAsB,CAAC;QACjG,OAAO,GAAG,CAAC,IAAI,IAAI,IAAA,eAAQ,EAAC,OAAO,CAAC,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,IAAA,eAAQ,EAAC,OAAO,CAAC,CAAC;IAAC,CAAC;AACvC,CAAC;AAED,SAAS,SAAS,CAAC,GAAW,EAAE,WAAoB;IAClD,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,SAAS,IAAI,CAAC,OAAe;QAC3B,IAAI,OAAiB,CAAC;QACtB,IAAI,CAAC;YAAC,OAAO,GAAG,IAAA,gBAAW,EAAC,OAAO,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO;QAAC,CAAC;QAEzD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;gBAAE,SAAS;YACnC,MAAM,IAAI,GAAG,IAAA,WAAI,EAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YAClC,IAAI,IAAiC,CAAC;YACtC,IAAI,CAAC;gBAAC,IAAI,GAAG,IAAA,aAAQ,EAAC,IAAI,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC;gBAAC,SAAS;YAAC,CAAC;YAElD,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;gBACvB,IAAI,CAAC,IAAI,CAAC,CAAC;YACb,CAAC;iBAAM,IAAI,SAAS,CAAC,GAAG,CAAC,IAAA,cAAO,EAAC,KAAK,CAAC,CAAC,EAAE,CAAC;gBACzC,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;oBAC/C,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACnB,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,UAAU,CAAC,IAAY,EAAE,UAAkB;IAClD,MAAM,EAAE,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;IACpC,MAAM,EAAE,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAE9B,2BAA2B;IAC3B,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,yDAAyD,CAAC,CAAC;IACvF,IAAI,QAAQ,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,EAAE;QAAE,OAAO,GAAG,CAAC;IAC7D,IAAI,QAAQ,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC;QAAE,OAAO,EAAE,CAAC;IAElE,8DAA8D;IAC9D,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,yEAAyE,CAAC,CAAC;IAC1G,IAAI,WAAW,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,EAAE;QAAE,OAAO,EAAE,CAAC;IAElE,eAAe;IACf,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC;QAAE,OAAO,EAAE,CAAC;IAE1D,eAAe;IACf,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC;QAAE,OAAO,EAAE,CAAC;IAE1D,kBAAkB;IAClB,IAAI,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC;QAAE,OAAO,EAAE,CAAC;IAE/B,OAAO,CAAC,CAAC;AACX,CAAC;AAED,wEAAwE;AACxE,SAAS,iBAAiB,CAAC,MAAgB,EAAE,OAAe;IAC1D,MAAM,UAAU,GAAG,IAAA,yBAAc,EAAC,OAAO,CAAC,CAAC;IAC3C,IAAI,CAAC,IAAA,eAAU,EAAC,UAAU,CAAC;QAAE,OAAO,EAAE,CAAC;IAEvC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;QACxC,MAAM,EAAE,GAAG,oCAAe,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QACnD,MAAM,UAAU,GAAG,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAC7C,MAAM,OAAO,GAAmB,EAAE,CAAC;QAEnC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;gBAAE,SAAS;YAE/B,8BAA8B;YAC9B,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAmB,CAAC;YACpG,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;gBAC3B,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;gBACnD,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;gBAClF,OAAO,CAAC,IAAI,CAAC;oBACX,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,IAAI,EAAE,OAAO;oBACb,KAAK,EAAE,GAAG,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE;oBAChG,OAAO,EAAE,eAAe,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;iBAC9F,CAAC,CAAC;YACL,CAAC;YAED,wBAAwB;YACxB,MAAM,SAAS,GAAG,UAAU,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAe,CAAC;YAC9F,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;gBAC7B,OAAO,CAAC,IAAI,CAAC;oBACX,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;oBACnD,IAAI,EAAE,CAAC;oBACP,IAAI,EAAE,OAAO;oBACb,KAAK,EAAE,IAAI,CAAC,KAAK;oBACjB,OAAO,EAAE,kBAAkB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;iBAClE,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAEM,KAAK,UAAU,eAAe,CAAC,KAAuB,EAAE,GAAW;IACxE,MAAM,OAAO,GAAG,IAAA,cAAO,EAAC,KAAK,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC;IAE3C,IAAI,CAAC,IAAA,eAAU,EAAC,OAAO,CAAC,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,wBAAwB,OAAO,EAAE,EAAE,CAAC,CAAC;IACtE,CAAC;IAED,8DAA8D;IAC9D,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACrE,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC;IAE3C,4EAA4E;IAC5E,MAAM,YAAY,GAAG,iBAAiB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAExD,6EAA6E;IAC7E,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;IACrD,MAAM,WAAW,GAAmB,EAAE,CAAC;IAEvC,KAAK,MAAM,QAAQ,IAAI,KAAK,EAAE,CAAC;QAC7B,IAAI,WAAW,CAAC,MAAM,IAAI,UAAU,GAAG,CAAC;YAAE,MAAM;QAEhD,IAAI,OAAe,CAAC;QACpB,IAAI,CAAC;YAAC,OAAO,GAAG,IAAA,iBAAY,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,SAAS;QAAC,CAAC;QAErE,MAAM,OAAO,GAAG,IAAA,eAAQ,EAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAEhE,oCAAoC;QACpC,MAAM,aAAa,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;QAC5C,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC;YAC9D,WAAW,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,OAAO,EAAE,EAAE,CAAC,CAAC;QAC5G,CAAC;QAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,yCAAyC;YACzC,IAAI,SAAS,GAAG,CAAC,CAAC;YAClB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,MAAM,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;gBACtC,IAAI,CAAC,GAAG,SAAS;oBAAE,SAAS,GAAG,CAAC,CAAC;YACnC,CAAC;YACD,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;gBAClB,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC9D,WAAW,CAAC,IAAI,CAAC;oBACf,IAAI,EAAE,OAAO;oBACb,IAAI,EAAE,CAAC,GAAG,CAAC;oBACX,IAAI,EAAE,SAAS,IAAI,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;oBAC5C,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;oBACpC,OAAO,EAAE,GAAG;iBACb,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,sDAAsD;IACtD,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACxB,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI;YAAE,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3D,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,4EAA4E;IAC5E,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,MAAM,GAAmB,EAAE,CAAC;IAElC,KAAK,MAAM,CAAC,IAAI,YAAY,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;QAClC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAAC,CAAC;IACxD,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;QAClC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAAC,CAAC;IACxD,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;IAExC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,mBAAmB,KAAK,CAAC,KAAK,QAAQ,OAAO,EAAE,CAAC;IACzD,CAAC;IAED,MAAM,WAAW,GAAG;QAClB,cAAc,KAAK,CAAC,KAAK,OAAO,GAAG,CAAC,MAAM,aAAa,YAAY,CAAC,MAAM,gBAAgB,KAAK,CAAC,MAAM,mBAAmB;KAC1H,CAAC;IACF,IAAI,QAAQ,GAAG,EAAE,CAAC;IAElB,KAAK,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;QACpB,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACxB,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YACnC,QAAQ,GAAG,CAAC,CAAC,IAAI,CAAC;QACpB,CAAC;QACD,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YACf,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;QAC5D,CAAC;aAAM,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC9B,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QAChE,CAAC;IACH,CAAC;IAED,OAAO,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAChC,CAAC"}
|
|
@@ -9,12 +9,16 @@ export interface RetrieveOptions {
|
|
|
9
9
|
k?: number;
|
|
10
10
|
includeGraph?: boolean;
|
|
11
11
|
graphDepth?: number;
|
|
12
|
+
workingDiff?: string;
|
|
12
13
|
}
|
|
13
14
|
export declare class HybridMemory {
|
|
14
15
|
private readonly vectorStore;
|
|
15
16
|
private readonly graphStore;
|
|
16
17
|
constructor(vectorStore: VectorStore, graphStore: GraphStore);
|
|
17
18
|
retrieve(query: string, opts?: RetrieveOptions): Promise<RetrievedContext>;
|
|
19
|
+
private retrieveGraphContext;
|
|
20
|
+
/** Find commits (from graph) that changed any of the given file paths. */
|
|
21
|
+
private getCommitsForFiles;
|
|
18
22
|
private buildContextString;
|
|
19
23
|
}
|
|
20
24
|
//# sourceMappingURL=HybridMemory.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HybridMemory.d.ts","sourceRoot":"","sources":["../../src/memory/HybridMemory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC5E,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"HybridMemory.d.ts","sourceRoot":"","sources":["../../src/memory/HybridMemory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC5E,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAsC,MAAM,wBAAwB,CAAC;AAGxG,MAAM,WAAW,gBAAgB;IAC/B,aAAa,EAAE,cAAc,EAAE,CAAC;IAChC,YAAY,EAAE,SAAS,EAAE,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,YAAY;IAErB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,UAAU;gBADV,WAAW,EAAE,WAAW,EACxB,UAAU,EAAE,UAAU;IAGnC,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,eAAoB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAiBpF,OAAO,CAAC,oBAAoB;IAyD5B,0EAA0E;IAC1E,OAAO,CAAC,kBAAkB;IAqB1B,OAAO,CAAC,kBAAkB;CA+E3B"}
|
|
@@ -16,57 +16,148 @@ class HybridMemory {
|
|
|
16
16
|
const vectorResults = await this.vectorStore.search(query, k);
|
|
17
17
|
let graphResults = [];
|
|
18
18
|
if (includeGraph) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
graphResults = this.retrieveGraphContext(query, vectorResults);
|
|
20
|
+
}
|
|
21
|
+
const combined = this.buildContextString(query, vectorResults, graphResults, opts.workingDiff);
|
|
22
|
+
return { vectorResults, graphResults, combined };
|
|
23
|
+
}
|
|
24
|
+
retrieveGraphContext(query, vectorResults) {
|
|
25
|
+
const stopWords = new Set(['the', 'and', 'for', 'with', 'from', 'that', 'this', 'are', 'has', 'have', 'not', 'but', 'can', 'when']);
|
|
26
|
+
const tokens = query
|
|
27
|
+
.toLowerCase()
|
|
28
|
+
.split(/[\s\W]+/)
|
|
29
|
+
.filter(t => t.length > 2 && !stopWords.has(t));
|
|
30
|
+
const results = [];
|
|
31
|
+
const seen = new Set();
|
|
32
|
+
const add = (node) => {
|
|
33
|
+
if (!seen.has(node.id)) {
|
|
34
|
+
seen.add(node.id);
|
|
35
|
+
results.push(node);
|
|
25
36
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
37
|
+
};
|
|
38
|
+
// 1. Exact symbol matches — query each token
|
|
39
|
+
for (const token of tokens) {
|
|
40
|
+
const fnNodes = this.graphStore.query({ type: 'function', label: token, exact: true });
|
|
41
|
+
fnNodes.forEach(add);
|
|
42
|
+
}
|
|
43
|
+
// 2. Seed graph traversal from vector search results
|
|
44
|
+
const paths = new Set();
|
|
45
|
+
for (const r of vectorResults) {
|
|
46
|
+
const relPath = r.document.metadata.relativePath;
|
|
47
|
+
if (relPath)
|
|
48
|
+
paths.add(relPath);
|
|
49
|
+
}
|
|
50
|
+
for (const path of paths) {
|
|
51
|
+
const fileNode = this.graphStore.getNode(`file:${path}`);
|
|
52
|
+
if (fileNode) {
|
|
53
|
+
add(fileNode);
|
|
54
|
+
const neighbors = this.graphStore.getNeighbors(fileNode.id);
|
|
55
|
+
neighbors.slice(0, 5).forEach(add);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// 3. Substring keyword matches
|
|
59
|
+
for (const token of tokens.slice(0, 3)) {
|
|
60
|
+
const partial = this.graphStore.query({ label: token }).slice(0, 5);
|
|
61
|
+
partial.forEach(add);
|
|
62
|
+
}
|
|
63
|
+
// 4. Sort: exact matches first
|
|
64
|
+
const tokenSet = new Set(tokens);
|
|
65
|
+
results.sort((a, b) => {
|
|
66
|
+
const score = (n) => {
|
|
67
|
+
const label = n.label.toLowerCase();
|
|
68
|
+
if (tokenSet.has(label))
|
|
69
|
+
return 100;
|
|
70
|
+
if (tokens.some(t => label.includes(t) || t.includes(label)))
|
|
71
|
+
return 50;
|
|
72
|
+
return 0;
|
|
73
|
+
};
|
|
74
|
+
return score(b) - score(a);
|
|
75
|
+
});
|
|
76
|
+
return results;
|
|
77
|
+
}
|
|
78
|
+
/** Find commits (from graph) that changed any of the given file paths. */
|
|
79
|
+
getCommitsForFiles(filePaths) {
|
|
80
|
+
const commits = [];
|
|
81
|
+
const seen = new Set();
|
|
82
|
+
for (const path of filePaths) {
|
|
83
|
+
const normalizedPath = path.replace(/\\/g, '/');
|
|
84
|
+
// dependantsOf returns nodes with edges pointing TO fileNode — i.e., commits that changed it
|
|
85
|
+
const dependants = this.graphStore.dependantsOf(`file:${normalizedPath}`);
|
|
86
|
+
for (const node of dependants) {
|
|
87
|
+
if (node.type === 'commit' && !seen.has(node.id)) {
|
|
88
|
+
seen.add(node.id);
|
|
89
|
+
commits.push(node);
|
|
32
90
|
}
|
|
33
91
|
}
|
|
34
|
-
// Also query graph by keyword
|
|
35
|
-
const graphKeywords = this.graphStore.query({ label: query.split(' ')[0] }).slice(0, 3);
|
|
36
|
-
graphResults.push(...graphKeywords);
|
|
37
|
-
// Deduplicate
|
|
38
|
-
const seen = new Set();
|
|
39
|
-
graphResults = graphResults.filter((n) => {
|
|
40
|
-
if (seen.has(n.id))
|
|
41
|
-
return false;
|
|
42
|
-
seen.add(n.id);
|
|
43
|
-
return true;
|
|
44
|
-
});
|
|
45
92
|
}
|
|
46
|
-
|
|
47
|
-
|
|
93
|
+
// Sort by timestamp descending (most recent first)
|
|
94
|
+
commits.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
|
|
95
|
+
return commits.slice(0, 8);
|
|
48
96
|
}
|
|
49
|
-
buildContextString(query, vectorResults, graphResults) {
|
|
97
|
+
buildContextString(query, vectorResults, graphResults, workingDiff) {
|
|
50
98
|
const parts = [`# Context for: "${query}"\n`];
|
|
99
|
+
// ── Code Snippets ──────────────────────────────────────────────────────
|
|
51
100
|
if (vectorResults.length > 0) {
|
|
52
101
|
parts.push('## Relevant Code Snippets\n');
|
|
53
102
|
for (const r of vectorResults) {
|
|
54
103
|
const path = r.document.metadata.relativePath ?? r.document.metadata.path ?? 'unknown';
|
|
55
|
-
|
|
104
|
+
const scoreLabel = r.score > 0 ? ` (score: ${r.score.toFixed(3)})` : '';
|
|
105
|
+
parts.push(`### ${path}${scoreLabel}\n\`\`\`\n${r.document.text.slice(0, 400)}\n\`\`\`\n`);
|
|
56
106
|
}
|
|
57
107
|
}
|
|
108
|
+
// ── Structural Context ─────────────────────────────────────────────────
|
|
58
109
|
if (graphResults.length > 0) {
|
|
59
110
|
parts.push('## Structural Context\n');
|
|
111
|
+
const byFile = new Map();
|
|
112
|
+
const fileNodes = [];
|
|
60
113
|
for (const node of graphResults) {
|
|
61
114
|
if (node.type === 'file') {
|
|
62
|
-
|
|
115
|
+
fileNodes.push(node);
|
|
63
116
|
}
|
|
64
117
|
else if (node.type === 'function') {
|
|
65
|
-
|
|
118
|
+
const fn = node;
|
|
119
|
+
const key = fn.filePath.replace(/\\/g, '/');
|
|
120
|
+
if (!byFile.has(key))
|
|
121
|
+
byFile.set(key, []);
|
|
122
|
+
byFile.get(key).push(fn);
|
|
66
123
|
}
|
|
67
124
|
}
|
|
125
|
+
for (const [filePath, fns] of byFile) {
|
|
126
|
+
parts.push(`### \`${filePath}\``);
|
|
127
|
+
for (const fn of fns.slice(0, 8)) {
|
|
128
|
+
const qualifiedName = fn.parentClass ? `${fn.parentClass}.${fn.label}` : fn.label;
|
|
129
|
+
const sig = `${qualifiedName}(${fn.parameters.join(', ')})${fn.returnType ? ': ' + fn.returnType : ''}`;
|
|
130
|
+
parts.push(` - \`${sig}\` — L${fn.line}`);
|
|
131
|
+
}
|
|
132
|
+
parts.push('');
|
|
133
|
+
}
|
|
134
|
+
for (const node of fileNodes) {
|
|
135
|
+
parts.push(`- File: \`${node.path}\` (exports: ${node.exports.slice(0, 5).join(', ')})`);
|
|
136
|
+
}
|
|
68
137
|
parts.push('');
|
|
69
138
|
}
|
|
139
|
+
// ── Git History ────────────────────────────────────────────────────────
|
|
140
|
+
const filePaths = vectorResults
|
|
141
|
+
.map(r => (r.document.metadata.relativePath ?? r.document.metadata.path ?? ''))
|
|
142
|
+
.filter(Boolean);
|
|
143
|
+
if (filePaths.length > 0) {
|
|
144
|
+
const commits = this.getCommitsForFiles(filePaths);
|
|
145
|
+
if (commits.length > 0) {
|
|
146
|
+
parts.push('## Recent Git History\n');
|
|
147
|
+
for (const c of commits) {
|
|
148
|
+
const date = new Date(c.timestamp).toLocaleDateString('pt-BR', { day: '2-digit', month: '2-digit', year: '2-digit' });
|
|
149
|
+
const files = c.filesChanged.slice(0, 3).join(', ');
|
|
150
|
+
const more = c.filesChanged.length > 3 ? ` +${c.filesChanged.length - 3}` : '';
|
|
151
|
+
parts.push(`- \`${c.sha.slice(0, 7)}\` ${c.message} *(${date})* — ${files}${more}`);
|
|
152
|
+
}
|
|
153
|
+
parts.push('');
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
// ── Working Diff ───────────────────────────────────────────────────────
|
|
157
|
+
if (workingDiff && workingDiff.trim().length > 0) {
|
|
158
|
+
parts.push('## Uncommitted Changes (git diff HEAD)\n');
|
|
159
|
+
parts.push(`\`\`\`diff\n${workingDiff.slice(0, 2000)}\n\`\`\`\n`);
|
|
160
|
+
}
|
|
70
161
|
return parts.join('\n');
|
|
71
162
|
}
|
|
72
163
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HybridMemory.js","sourceRoot":"","sources":["../../src/memory/HybridMemory.ts"],"names":[],"mappings":";;;AAEA,kDAA4C;
|
|
1
|
+
{"version":3,"file":"HybridMemory.js","sourceRoot":"","sources":["../../src/memory/HybridMemory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
interface PipelineTensor {
|
|
2
|
+
data: Float32Array;
|
|
3
|
+
dims: number[];
|
|
4
|
+
}
|
|
5
|
+
type EmbedPipeline = (texts: string[], options?: Record<string, unknown>) => Promise<PipelineTensor>;
|
|
6
|
+
export interface DownloadProgress {
|
|
7
|
+
file: string;
|
|
8
|
+
progress: number;
|
|
9
|
+
loaded: number;
|
|
10
|
+
total: number;
|
|
11
|
+
status: 'initiate' | 'download' | 'progress' | 'done' | 'ready' | 'loading';
|
|
12
|
+
}
|
|
13
|
+
export type ProgressCallback = (info: DownloadProgress) => void;
|
|
14
|
+
/** True if the pipeline has been loaded into memory this process. */
|
|
15
|
+
export declare function isPipelineReady(): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Load (and optionally download) the embedding model.
|
|
18
|
+
* Returns the pipeline or null if loading fails.
|
|
19
|
+
* @param onProgress Called for each download/load progress event.
|
|
20
|
+
*/
|
|
21
|
+
export declare function ensureModel(onProgress?: ProgressCallback): Promise<EmbedPipeline | null>;
|
|
22
|
+
/** Get the cached pipeline (null if not yet loaded). */
|
|
23
|
+
export declare function getCachedPipeline(): EmbedPipeline | null;
|
|
24
|
+
/** Reset the cache (for tests). */
|
|
25
|
+
export declare function resetPipeline(): void;
|
|
26
|
+
/**
|
|
27
|
+
* Extract individual embedding vectors from a batched pipeline tensor.
|
|
28
|
+
* The tensor's `data` is a flat Float32Array of shape [batch, dim].
|
|
29
|
+
*/
|
|
30
|
+
export declare function extractEmbeddings(tensor: PipelineTensor): number[][];
|
|
31
|
+
/**
|
|
32
|
+
* Embed texts using a worker thread when available (production), falling back
|
|
33
|
+
* to the main-thread pipeline in dev/test environments.
|
|
34
|
+
*/
|
|
35
|
+
export declare function embedTexts(texts: string[]): Promise<number[][]>;
|
|
36
|
+
export {};
|
|
37
|
+
//# sourceMappingURL=modelManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modelManager.d.ts","sourceRoot":"","sources":["../../src/utils/modelManager.ts"],"names":[],"mappings":"AAKA,UAAU,cAAc;IACtB,IAAI,EAAE,YAAY,CAAC;IACnB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,KAAK,aAAa,GAAG,CACnB,KAAK,EAAE,MAAM,EAAE,EACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC9B,OAAO,CAAC,cAAc,CAAC,CAAC;AAE7B,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,UAAU,GAAG,UAAU,GAAG,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;CAC7E;AAED,MAAM,MAAM,gBAAgB,GAAG,CAAC,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAC;AAIhE,qEAAqE;AACrE,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,UAAU,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAkC9F;AAED,wDAAwD;AACxD,wBAAgB,iBAAiB,IAAI,aAAa,GAAG,IAAI,CAExD;AAED,mCAAmC;AACnC,wBAAgB,aAAa,IAAI,IAAI,CAEpC;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,EAAE,EAAE,CAOpE;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAUrE"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isPipelineReady = isPipelineReady;
|
|
4
|
+
exports.ensureModel = ensureModel;
|
|
5
|
+
exports.getCachedPipeline = getCachedPipeline;
|
|
6
|
+
exports.resetPipeline = resetPipeline;
|
|
7
|
+
exports.extractEmbeddings = extractEmbeddings;
|
|
8
|
+
exports.embedTexts = embedTexts;
|
|
9
|
+
const logger_js_1 = require("./logger.js");
|
|
10
|
+
const workerPool_js_1 = require("./workerPool.js");
|
|
11
|
+
const MODEL_ID = 'Xenova/all-MiniLM-L6-v2';
|
|
12
|
+
let cachedPipeline = null;
|
|
13
|
+
/** True if the pipeline has been loaded into memory this process. */
|
|
14
|
+
function isPipelineReady() {
|
|
15
|
+
return cachedPipeline !== null;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Load (and optionally download) the embedding model.
|
|
19
|
+
* Returns the pipeline or null if loading fails.
|
|
20
|
+
* @param onProgress Called for each download/load progress event.
|
|
21
|
+
*/
|
|
22
|
+
async function ensureModel(onProgress) {
|
|
23
|
+
if (cachedPipeline)
|
|
24
|
+
return cachedPipeline;
|
|
25
|
+
try {
|
|
26
|
+
const { pipeline, env } = await import('@xenova/transformers');
|
|
27
|
+
// Allow overriding cache dir via env var
|
|
28
|
+
if (process.env.FIRECODE_MODEL_CACHE) {
|
|
29
|
+
env.cacheDir = process.env.FIRECODE_MODEL_CACHE;
|
|
30
|
+
}
|
|
31
|
+
const progressCb = onProgress
|
|
32
|
+
? (info) => {
|
|
33
|
+
onProgress({
|
|
34
|
+
file: String(info.file ?? info.name ?? ''),
|
|
35
|
+
progress: typeof info.progress === 'number' ? info.progress : 0,
|
|
36
|
+
loaded: typeof info.loaded === 'number' ? info.loaded : 0,
|
|
37
|
+
total: typeof info.total === 'number' ? info.total : 0,
|
|
38
|
+
status: info.status ?? 'progress',
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
: undefined;
|
|
42
|
+
const pipe = await pipeline('feature-extraction', MODEL_ID, {
|
|
43
|
+
progress_callback: progressCb,
|
|
44
|
+
});
|
|
45
|
+
cachedPipeline = pipe;
|
|
46
|
+
logger_js_1.logger.info({ model: MODEL_ID }, 'Embedding model loaded');
|
|
47
|
+
return cachedPipeline;
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
logger_js_1.logger.warn({ err: String(err) }, 'Could not load embedding model — falling back to text similarity');
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/** Get the cached pipeline (null if not yet loaded). */
|
|
55
|
+
function getCachedPipeline() {
|
|
56
|
+
return cachedPipeline;
|
|
57
|
+
}
|
|
58
|
+
/** Reset the cache (for tests). */
|
|
59
|
+
function resetPipeline() {
|
|
60
|
+
cachedPipeline = null;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Extract individual embedding vectors from a batched pipeline tensor.
|
|
64
|
+
* The tensor's `data` is a flat Float32Array of shape [batch, dim].
|
|
65
|
+
*/
|
|
66
|
+
function extractEmbeddings(tensor) {
|
|
67
|
+
const [batchSize, dim] = tensor.dims;
|
|
68
|
+
const result = [];
|
|
69
|
+
for (let i = 0; i < batchSize; i++) {
|
|
70
|
+
result.push(Array.from(tensor.data.slice(i * dim, (i + 1) * dim)));
|
|
71
|
+
}
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Embed texts using a worker thread when available (production), falling back
|
|
76
|
+
* to the main-thread pipeline in dev/test environments.
|
|
77
|
+
*/
|
|
78
|
+
async function embedTexts(texts) {
|
|
79
|
+
// Try worker thread first — returns null in dev/test mode or after worker crash
|
|
80
|
+
const workerResult = await (0, workerPool_js_1.workerEmbed)(texts).catch(() => null);
|
|
81
|
+
if (workerResult !== null)
|
|
82
|
+
return workerResult;
|
|
83
|
+
// Main-thread fallback
|
|
84
|
+
const pipe = await ensureModel();
|
|
85
|
+
if (!pipe)
|
|
86
|
+
return texts.map(() => []);
|
|
87
|
+
const tensor = await pipe(texts, { pooling: 'mean', normalize: true });
|
|
88
|
+
return extractEmbeddings(tensor);
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=modelManager.js.map
|