@toolbaux/guardian 0.1.21 → 0.1.22
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/commands/mcp-serve.js +50 -17
- package/package.json +1 -1
|
@@ -311,30 +311,63 @@ async function search(args) {
|
|
|
311
311
|
// Frontend pages: match path or component
|
|
312
312
|
const pages = (d.frontend_pages || []).filter((p) => p.path?.toLowerCase().includes(q) || p.component?.toLowerCase().includes(q) ||
|
|
313
313
|
p.api_calls?.some((c) => c.toLowerCase().includes(q))).slice(0, 5).map((p) => `${p.path} → ${p.component}`);
|
|
314
|
-
// Functions: search
|
|
314
|
+
// Functions: ranked search across names, literals, calls — capped at 10 to prevent flooding
|
|
315
315
|
const fnHits = [];
|
|
316
316
|
const fi = await loadFuncIntel();
|
|
317
317
|
if (fi) {
|
|
318
|
-
//
|
|
318
|
+
// Build a field map: file → field names (augments fn hits with model fields)
|
|
319
|
+
const fileToFields = new Map();
|
|
320
|
+
for (const m of Object.values(d.model_registry || {})) {
|
|
321
|
+
if (!m.file)
|
|
322
|
+
continue;
|
|
323
|
+
const existing = fileToFields.get(m.file) ?? [];
|
|
324
|
+
fileToFields.set(m.file, [...existing, ...(m.fields ?? [])]);
|
|
325
|
+
}
|
|
326
|
+
const scored = [];
|
|
327
|
+
const seen = new Set();
|
|
328
|
+
for (const fn of (fi.functions ?? [])) {
|
|
329
|
+
const nameNorm = (fn.name ?? "").toLowerCase();
|
|
330
|
+
const fileNorm = (fn.file ?? "").toLowerCase();
|
|
331
|
+
const callsNorm = (fn.calls ?? []).map((c) => c.toLowerCase());
|
|
332
|
+
const litsNorm = [...(fn.stringLiterals ?? []), ...(fn.regexPatterns ?? [])].map((l) => l.toLowerCase());
|
|
333
|
+
let score = 0;
|
|
334
|
+
if (nameNorm === q)
|
|
335
|
+
score = 1.0;
|
|
336
|
+
else if (nameNorm.includes(q))
|
|
337
|
+
score = 0.7;
|
|
338
|
+
else if (callsNorm.some((c) => c.includes(q)))
|
|
339
|
+
score = 0.5;
|
|
340
|
+
else if (litsNorm.some((l) => l.includes(q)))
|
|
341
|
+
score = 0.3;
|
|
342
|
+
else if (fileNorm.includes(q))
|
|
343
|
+
score = 0.2;
|
|
344
|
+
if (score > 0) {
|
|
345
|
+
scored.push({ fn, score });
|
|
346
|
+
seen.add(`${fn.file}:${fn.name}`);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
// Also surface literal_index hits not already captured
|
|
319
350
|
const litIndex = fi.literal_index ?? {};
|
|
320
351
|
for (const [key, hits] of Object.entries(litIndex)) {
|
|
321
|
-
if (key.includes(q))
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
}
|
|
352
|
+
if (!key.includes(q))
|
|
353
|
+
continue;
|
|
354
|
+
for (const h of hits) {
|
|
355
|
+
const uid = `${h.file}:${h.function}`;
|
|
356
|
+
if (seen.has(uid))
|
|
357
|
+
continue;
|
|
358
|
+
seen.add(uid);
|
|
359
|
+
const fn = fi.functions.find((f) => f.file === h.file && f.name === h.function);
|
|
360
|
+
scored.push({ fn: fn ?? { name: h.function, file: h.file, lines: [h.line, h.line], calls: [], stringLiterals: [], regexPatterns: [] }, score: 0.25 });
|
|
325
361
|
}
|
|
326
|
-
if (fnHits.length >= 10)
|
|
327
|
-
break;
|
|
328
362
|
}
|
|
329
|
-
//
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
}
|
|
363
|
+
// Sort by score desc, take top 10
|
|
364
|
+
scored.sort((a, b) => b.score - a.score);
|
|
365
|
+
const projectRoot = process.cwd();
|
|
366
|
+
for (const { fn } of scored.slice(0, 10)) {
|
|
367
|
+
const relFile = fn.file?.startsWith("/") ? require("path").relative(projectRoot, fn.file) : fn.file;
|
|
368
|
+
const fields = fileToFields.get(fn.file) ?? [];
|
|
369
|
+
const fieldSuffix = fields.length > 0 ? ` fields:${fields.slice(0, 5).join(",")}` : "";
|
|
370
|
+
fnHits.push(`${fn.name} [${relFile}:${fn.lines?.[0]}]${fieldSuffix}`);
|
|
338
371
|
}
|
|
339
372
|
}
|
|
340
373
|
return compact({
|
package/package.json
CHANGED