@mcp-graph-workflow/mcp-graph 5.6.0 → 5.7.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.
Files changed (83) hide show
  1. package/README.md +2 -2
  2. package/dist/api/routes/code-graph.d.ts.map +1 -1
  3. package/dist/api/routes/code-graph.js +4 -1
  4. package/dist/api/routes/code-graph.js.map +1 -1
  5. package/dist/core/code/code-indexer.d.ts.map +1 -1
  6. package/dist/core/code/code-indexer.js +17 -2
  7. package/dist/core/code/code-indexer.js.map +1 -1
  8. package/dist/core/code/code-types.d.ts +1 -0
  9. package/dist/core/code/code-types.d.ts.map +1 -1
  10. package/dist/core/code/code-types.js.map +1 -1
  11. package/dist/core/code/ts-analyzer.d.ts +6 -0
  12. package/dist/core/code/ts-analyzer.d.ts.map +1 -1
  13. package/dist/core/code/ts-analyzer.js +9 -0
  14. package/dist/core/code/ts-analyzer.js.map +1 -1
  15. package/dist/core/importer/import-graph.d.ts +23 -0
  16. package/dist/core/importer/import-graph.d.ts.map +1 -0
  17. package/dist/core/importer/import-graph.js +127 -0
  18. package/dist/core/importer/import-graph.js.map +1 -0
  19. package/dist/core/rag/benchmark-indexer.d.ts +32 -0
  20. package/dist/core/rag/benchmark-indexer.d.ts.map +1 -0
  21. package/dist/core/rag/benchmark-indexer.js +85 -0
  22. package/dist/core/rag/benchmark-indexer.js.map +1 -0
  23. package/dist/core/rag/citation-mapper.d.ts +32 -0
  24. package/dist/core/rag/citation-mapper.d.ts.map +1 -0
  25. package/dist/core/rag/citation-mapper.js +45 -0
  26. package/dist/core/rag/citation-mapper.js.map +1 -0
  27. package/dist/core/rag/enrichment-pipeline.d.ts +48 -0
  28. package/dist/core/rag/enrichment-pipeline.d.ts.map +1 -0
  29. package/dist/core/rag/enrichment-pipeline.js +127 -0
  30. package/dist/core/rag/enrichment-pipeline.js.map +1 -0
  31. package/dist/core/rag/post-retrieval.d.ts +40 -0
  32. package/dist/core/rag/post-retrieval.d.ts.map +1 -0
  33. package/dist/core/rag/post-retrieval.js +119 -0
  34. package/dist/core/rag/post-retrieval.js.map +1 -0
  35. package/dist/core/rag/query-cache.d.ts +54 -0
  36. package/dist/core/rag/query-cache.d.ts.map +1 -0
  37. package/dist/core/rag/query-cache.js +104 -0
  38. package/dist/core/rag/query-cache.js.map +1 -0
  39. package/dist/core/rag/query-understanding.d.ts +37 -0
  40. package/dist/core/rag/query-understanding.d.ts.map +1 -0
  41. package/dist/core/rag/query-understanding.js +123 -0
  42. package/dist/core/rag/query-understanding.js.map +1 -0
  43. package/dist/core/rag/rag-trace.d.ts +67 -0
  44. package/dist/core/rag/rag-trace.d.ts.map +1 -0
  45. package/dist/core/rag/rag-trace.js +82 -0
  46. package/dist/core/rag/rag-trace.js.map +1 -0
  47. package/dist/core/rag/source-contribution.d.ts +37 -0
  48. package/dist/core/rag/source-contribution.d.ts.map +1 -0
  49. package/dist/core/rag/source-contribution.js +54 -0
  50. package/dist/core/rag/source-contribution.js.map +1 -0
  51. package/dist/core/store/sqlite-store.d.ts +9 -0
  52. package/dist/core/store/sqlite-store.d.ts.map +1 -1
  53. package/dist/core/store/sqlite-store.js +42 -0
  54. package/dist/core/store/sqlite-store.js.map +1 -1
  55. package/dist/mcp/tools/import-graph.d.ts +4 -0
  56. package/dist/mcp/tools/import-graph.d.ts.map +1 -0
  57. package/dist/mcp/tools/import-graph.js +81 -0
  58. package/dist/mcp/tools/import-graph.js.map +1 -0
  59. package/dist/mcp/tools/index.d.ts.map +1 -1
  60. package/dist/mcp/tools/index.js +2 -0
  61. package/dist/mcp/tools/index.js.map +1 -1
  62. package/dist/schemas/knowledge.schema.d.ts +2 -0
  63. package/dist/schemas/knowledge.schema.d.ts.map +1 -1
  64. package/dist/schemas/knowledge.schema.js +1 -0
  65. package/dist/schemas/knowledge.schema.js.map +1 -1
  66. package/dist/web/dashboard/dist/assets/{benchmark-tab-WCcv55oB.js → benchmark-tab-BoMsoQjO.js} +1 -1
  67. package/dist/web/dashboard/dist/assets/{context-tab-CYnMjkHN.js → context-tab-BLT4qQ77.js} +1 -1
  68. package/dist/web/dashboard/dist/assets/{gitnexus-tab-Dj0DERUy.js → gitnexus-tab-DDw7DUED.js} +4 -4
  69. package/dist/web/dashboard/dist/assets/{graph-tab-tI93ZxxW.js → graph-tab-DG9Q6nko.js} +1 -1
  70. package/dist/web/dashboard/dist/assets/{graph-utils-DeQEwmsr.js → graph-utils-BpYHKE87.js} +1 -1
  71. package/dist/web/dashboard/dist/assets/{index-DKvjo_C5.css → index-Cu23WCcu.css} +1 -1
  72. package/dist/web/dashboard/dist/assets/{index-B1PLsGu1.js → index-DtkPX5ZZ.js} +2 -2
  73. package/dist/web/dashboard/dist/assets/{index-NmopQGmQ.js → index-F9dY4AG_.js} +1 -1
  74. package/dist/web/dashboard/dist/assets/{insights-tab-X7u4J-xv.js → insights-tab-YN7G6mjm.js} +1 -1
  75. package/dist/web/dashboard/dist/assets/{journey-tab-Cpz6_3mB.js → journey-tab-BcweuR82.js} +1 -1
  76. package/dist/web/dashboard/dist/assets/{logs-tab-QB__4Xdl.js → logs-tab-BjdAURdy.js} +1 -1
  77. package/dist/web/dashboard/dist/assets/{memories-tab-Dry9wz7q.js → memories-tab-CQ2xM2aw.js} +1 -1
  78. package/dist/web/dashboard/dist/assets/{prd-backlog-tab-OXTksZKv.js → prd-backlog-tab-CIeCpE1a.js} +1 -1
  79. package/dist/web/dashboard/dist/assets/{siebel-tab-x7OCuCmb.js → siebel-tab-bj5CT4-Z.js} +1 -1
  80. package/dist/web/dashboard/dist/assets/{skills-tab-DeUEKmpZ.js → skills-tab-Bgk72mKO.js} +1 -1
  81. package/dist/web/dashboard/dist/assets/{style-C-e8BTyP.js → style-Da3qWU01.js} +1 -1
  82. package/dist/web/dashboard/dist/index.html +2 -2
  83. package/package.json +13 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"citation-mapper.d.ts","sourceRoot":"","sources":["../../../src/core/rag/citation-mapper.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAGlE,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC;AAID;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,QAAQ,EAAE,CAahE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,YAAY,CAoBvE"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Citation Mapper — maps search results to citations with source traceability.
3
+ *
4
+ * Each chunk in the assembled context gets a [N] citation marker,
5
+ * enabling users to trace information back to its source.
6
+ */
7
+ import { generateId } from "../utils/id.js";
8
+ const MAX_SNIPPET_LENGTH = 400;
9
+ /**
10
+ * Create citations from ranked results.
11
+ * Each result gets a position-based citation (1-indexed).
12
+ */
13
+ export function mapCitations(results) {
14
+ return results.map((r, i) => ({
15
+ id: generateId("cite"),
16
+ chunkId: r.id,
17
+ sourceType: r.sourceType,
18
+ sourceId: r.sourceId,
19
+ title: r.title,
20
+ snippet: r.content.length > MAX_SNIPPET_LENGTH
21
+ ? r.content.slice(0, MAX_SNIPPET_LENGTH)
22
+ : r.content,
23
+ relevanceScore: r.score,
24
+ position: i + 1,
25
+ }));
26
+ }
27
+ /**
28
+ * Build a cited context: assembled text with [N] markers + citation list + source breakdown.
29
+ */
30
+ export function buildCitedContext(results) {
31
+ if (results.length === 0) {
32
+ return { assembledText: "", citations: [], sourceBreakdown: {} };
33
+ }
34
+ const citations = mapCitations(results);
35
+ const sourceBreakdown = {};
36
+ const textParts = [];
37
+ for (let i = 0; i < results.length; i++) {
38
+ const r = results[i];
39
+ textParts.push(`[${i + 1}] ${r.content}`);
40
+ sourceBreakdown[r.sourceType] = (sourceBreakdown[r.sourceType] ?? 0) + 1;
41
+ }
42
+ const assembledText = textParts.join("\n\n");
43
+ return { assembledText, citations, sourceBreakdown };
44
+ }
45
+ //# sourceMappingURL=citation-mapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"citation-mapper.js","sourceRoot":"","sources":["../../../src/core/rag/citation-mapper.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAmB5C,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAE/B;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,OAAuB;IAClD,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QAC5B,EAAE,EAAE,UAAU,CAAC,MAAM,CAAC;QACtB,OAAO,EAAE,CAAC,CAAC,EAAE;QACb,UAAU,EAAE,CAAC,CAAC,UAAU;QACxB,QAAQ,EAAE,CAAC,CAAC,QAAQ;QACpB,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,kBAAkB;YAC5C,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,kBAAkB,CAAC;YACxC,CAAC,CAAC,CAAC,CAAC,OAAO;QACb,cAAc,EAAE,CAAC,CAAC,KAAK;QACvB,QAAQ,EAAE,CAAC,GAAG,CAAC;KAChB,CAAC,CAAC,CAAC;AACN,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAuB;IACvD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,aAAa,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC;IACnE,CAAC;IAED,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IACxC,MAAM,eAAe,GAA2B,EAAE,CAAC;IAEnD,MAAM,SAAS,GAAa,EAAE,CAAC;IAE/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACrB,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QAE1C,eAAe,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IAC3E,CAAC;IAED,MAAM,aAAa,GAAG,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAE7C,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;AACvD,CAAC"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Enrichment Pipeline — enriches text chunks with keywords, entities, and summaries
3
+ * before indexation into the knowledge store.
4
+ *
5
+ * Transforms raw TextChunks into EnrichedChunks with:
6
+ * - TF-IDF-based keyword extraction (top-N terms)
7
+ * - Regex-based entity detection (PascalCase, camelCase, file paths)
8
+ * - Auto-generated summary (first sentence or markdown heading)
9
+ * - Parent-child chunk linking for later chunk stitching
10
+ */
11
+ import type { TextChunk } from "./chunk-text.js";
12
+ export interface EnrichedChunk extends TextChunk {
13
+ /** Top-N keywords extracted via TF-IDF term frequency */
14
+ keywords: string[];
15
+ /** Detected entities: class names, function names, file paths */
16
+ entities: string[];
17
+ /** Auto-generated summary (first sentence or heading) */
18
+ summary: string;
19
+ /** Source type discriminator */
20
+ sourceType: string;
21
+ /** Reference to parent chunk index for chunk stitching */
22
+ parentChunkIndex?: number;
23
+ }
24
+ /**
25
+ * Extract top-N keywords from text using term frequency scoring.
26
+ * Uses the project tokenizer (handles PT + EN, strips stopwords).
27
+ */
28
+ export declare function extractKeywords(text: string, topN?: number): string[];
29
+ /**
30
+ * Extract named entities from text using regex patterns.
31
+ * Detects PascalCase types, camelCase functions, and file paths.
32
+ */
33
+ export declare function extractEntities(text: string): string[];
34
+ /**
35
+ * Generate a short summary from chunk content.
36
+ * Prefers markdown heading if present, otherwise first sentence.
37
+ */
38
+ export declare function generateSummary(text: string): string;
39
+ /**
40
+ * Enrich a single text chunk with keywords, entities, summary, and source metadata.
41
+ */
42
+ export declare function enrichChunk(chunk: TextChunk, sourceType: string, parentChunkIndex?: number): EnrichedChunk;
43
+ /**
44
+ * Enrich multiple chunks from the same document.
45
+ * Applies parent-child linking for multi-chunk documents.
46
+ */
47
+ export declare function enrichChunks(chunks: TextChunk[], sourceType: string): EnrichedChunk[];
48
+ //# sourceMappingURL=enrichment-pipeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enrichment-pipeline.d.ts","sourceRoot":"","sources":["../../../src/core/rag/enrichment-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAIjD,MAAM,WAAW,aAAc,SAAQ,SAAS;IAC9C,yDAAyD;IACzD,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,iEAAiE;IACjE,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,yDAAyD;IACzD,OAAO,EAAE,MAAM,CAAC;IAChB,gCAAgC;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAKD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,MAAsB,GAAG,MAAM,EAAE,CAepF;AAcD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAwBtD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CA0BpD;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,SAAS,EAChB,UAAU,EAAE,MAAM,EAClB,gBAAgB,CAAC,EAAE,MAAM,GACxB,aAAa,CAoBf;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,SAAS,EAAE,EACnB,UAAU,EAAE,MAAM,GACjB,aAAa,EAAE,CASjB"}
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Enrichment Pipeline — enriches text chunks with keywords, entities, and summaries
3
+ * before indexation into the knowledge store.
4
+ *
5
+ * Transforms raw TextChunks into EnrichedChunks with:
6
+ * - TF-IDF-based keyword extraction (top-N terms)
7
+ * - Regex-based entity detection (PascalCase, camelCase, file paths)
8
+ * - Auto-generated summary (first sentence or markdown heading)
9
+ * - Parent-child chunk linking for later chunk stitching
10
+ */
11
+ import { tokenize } from "../search/tokenizer.js";
12
+ import { logger } from "../utils/logger.js";
13
+ const MAX_SUMMARY_LENGTH = 200;
14
+ const DEFAULT_TOP_N = 5;
15
+ /**
16
+ * Extract top-N keywords from text using term frequency scoring.
17
+ * Uses the project tokenizer (handles PT + EN, strips stopwords).
18
+ */
19
+ export function extractKeywords(text, topN = DEFAULT_TOP_N) {
20
+ const tokens = tokenize(text);
21
+ if (tokens.length === 0)
22
+ return [];
23
+ // Count term frequencies
24
+ const freq = new Map();
25
+ for (const token of tokens) {
26
+ freq.set(token, (freq.get(token) ?? 0) + 1);
27
+ }
28
+ // Sort by frequency descending, then alphabetically for stability
29
+ const sorted = Array.from(freq.entries())
30
+ .sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]));
31
+ return sorted.slice(0, topN).map(([term]) => term);
32
+ }
33
+ // ── Entity detection patterns ──────────────────────────────
34
+ /** PascalCase: at least two words joined (e.g., GraphNode, SqliteStore) */
35
+ // eslint-disable-next-line security/detect-unsafe-regex -- bounded pattern, safe for short identifiers
36
+ const PASCAL_CASE_RE = /\b([A-Z][a-z]+(?:[A-Z][a-z0-9]*)+)\b/g;
37
+ /** camelCase: starts lowercase, has at least one uppercase (e.g., findNextTask) */
38
+ const CAMEL_CASE_RE = /\b([a-z][a-zA-Z0-9]*[A-Z][a-zA-Z0-9]*)\b/g;
39
+ /** File paths: src/... or similar path patterns ending in common extensions */
40
+ const FILE_PATH_RE = /\b((?:src|lib|dist|test|tests)\/[\w\-./]+\.(?:ts|js|tsx|jsx|json|md|sql))\b/g;
41
+ /**
42
+ * Extract named entities from text using regex patterns.
43
+ * Detects PascalCase types, camelCase functions, and file paths.
44
+ */
45
+ export function extractEntities(text) {
46
+ const entities = new Set();
47
+ let match;
48
+ // PascalCase (reset lastIndex before each scan)
49
+ PASCAL_CASE_RE.lastIndex = 0;
50
+ while ((match = PASCAL_CASE_RE.exec(text)) !== null) {
51
+ entities.add(match[1]);
52
+ }
53
+ // camelCase
54
+ CAMEL_CASE_RE.lastIndex = 0;
55
+ while ((match = CAMEL_CASE_RE.exec(text)) !== null) {
56
+ entities.add(match[1]);
57
+ }
58
+ // File paths
59
+ FILE_PATH_RE.lastIndex = 0;
60
+ while ((match = FILE_PATH_RE.exec(text)) !== null) {
61
+ entities.add(match[1]);
62
+ }
63
+ return Array.from(entities);
64
+ }
65
+ /**
66
+ * Generate a short summary from chunk content.
67
+ * Prefers markdown heading if present, otherwise first sentence.
68
+ */
69
+ export function generateSummary(text) {
70
+ const trimmed = text.trim();
71
+ if (!trimmed)
72
+ return "";
73
+ // Check for markdown heading
74
+ const headingMatch = trimmed.match(/^#{1,6}\s+(.+)/m);
75
+ if (headingMatch) {
76
+ const heading = headingMatch[1].trim();
77
+ return heading.length > MAX_SUMMARY_LENGTH
78
+ ? heading.slice(0, MAX_SUMMARY_LENGTH)
79
+ : heading;
80
+ }
81
+ // First sentence (ends with . ! or ?)
82
+ const sentenceMatch = trimmed.match(/^[^.!?]+[.!?]/);
83
+ if (sentenceMatch) {
84
+ const sentence = sentenceMatch[0].trim();
85
+ return sentence.length > MAX_SUMMARY_LENGTH
86
+ ? sentence.slice(0, MAX_SUMMARY_LENGTH)
87
+ : sentence;
88
+ }
89
+ // Fallback: truncate to MAX_SUMMARY_LENGTH
90
+ return trimmed.length > MAX_SUMMARY_LENGTH
91
+ ? trimmed.slice(0, MAX_SUMMARY_LENGTH)
92
+ : trimmed;
93
+ }
94
+ /**
95
+ * Enrich a single text chunk with keywords, entities, summary, and source metadata.
96
+ */
97
+ export function enrichChunk(chunk, sourceType, parentChunkIndex) {
98
+ const keywords = extractKeywords(chunk.content);
99
+ const entities = extractEntities(chunk.content);
100
+ const summary = generateSummary(chunk.content);
101
+ logger.debug("Chunk enriched", {
102
+ index: chunk.index,
103
+ sourceType,
104
+ keywordCount: keywords.length,
105
+ entityCount: entities.length,
106
+ });
107
+ return {
108
+ ...chunk,
109
+ keywords,
110
+ entities,
111
+ summary,
112
+ sourceType,
113
+ parentChunkIndex,
114
+ };
115
+ }
116
+ /**
117
+ * Enrich multiple chunks from the same document.
118
+ * Applies parent-child linking for multi-chunk documents.
119
+ */
120
+ export function enrichChunks(chunks, sourceType) {
121
+ if (chunks.length <= 1) {
122
+ return chunks.map((c) => enrichChunk(c, sourceType));
123
+ }
124
+ // For multi-chunk documents, first chunk (index 0) is the "parent" reference
125
+ return chunks.map((c, i) => enrichChunk(c, sourceType, i === 0 ? undefined : 0));
126
+ }
127
+ //# sourceMappingURL=enrichment-pipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enrichment-pipeline.js","sourceRoot":"","sources":["../../../src/core/rag/enrichment-pipeline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Post-Retrieval Pipeline — processes search results after initial retrieval.
3
+ *
4
+ * Pipeline stages:
5
+ * 1. Deduplication — remove results with identical content
6
+ * 2. Reranking — boost results with higher query keyword overlap
7
+ * 3. Chunk stitching — merge adjacent chunks from the same source
8
+ * 4. Limit — enforce maxResults
9
+ */
10
+ import type { RankedResult } from "./multi-strategy-retrieval.js";
11
+ export interface PostRetrievalOptions {
12
+ query: string;
13
+ results: RankedResult[];
14
+ maxResults: number;
15
+ chunkMeta?: Map<string, number>;
16
+ }
17
+ export interface PostRetrievalResult {
18
+ results: RankedResult[];
19
+ deduplicated: number;
20
+ stitchedChunks: number;
21
+ }
22
+ /**
23
+ * Remove results with identical content, keeping the highest-scored one.
24
+ */
25
+ export declare function deduplicateResults(results: RankedResult[]): RankedResult[];
26
+ /**
27
+ * Rerank results by keyword overlap with the query.
28
+ * Combines original score with keyword overlap boost.
29
+ */
30
+ export declare function rerankByKeywordOverlap(results: RankedResult[], query: string): RankedResult[];
31
+ /**
32
+ * Merge adjacent chunks from the same source document.
33
+ * Chunks are considered adjacent if their chunk indices differ by 1.
34
+ */
35
+ export declare function stitchAdjacentChunks(results: RankedResult[], chunkMeta: Map<string, number>): RankedResult[];
36
+ /**
37
+ * Full post-retrieval pipeline.
38
+ */
39
+ export declare function postRetrievalPipeline(options: PostRetrievalOptions): PostRetrievalResult;
40
+ //# sourceMappingURL=post-retrieval.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post-retrieval.d.ts","sourceRoot":"","sources":["../../../src/core/rag/post-retrieval.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAIlE,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,YAAY,EAAE,CAY1E;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,YAAY,EAAE,EACvB,KAAK,EAAE,MAAM,GACZ,YAAY,EAAE,CAchB;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,YAAY,EAAE,EACvB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC7B,YAAY,EAAE,CAmDhB;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,oBAAoB,GAAG,mBAAmB,CA2BxF"}
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Post-Retrieval Pipeline — processes search results after initial retrieval.
3
+ *
4
+ * Pipeline stages:
5
+ * 1. Deduplication — remove results with identical content
6
+ * 2. Reranking — boost results with higher query keyword overlap
7
+ * 3. Chunk stitching — merge adjacent chunks from the same source
8
+ * 4. Limit — enforce maxResults
9
+ */
10
+ import { tokenize } from "../search/tokenizer.js";
11
+ import { logger } from "../utils/logger.js";
12
+ /**
13
+ * Remove results with identical content, keeping the highest-scored one.
14
+ */
15
+ export function deduplicateResults(results) {
16
+ const seen = new Map();
17
+ for (const result of results) {
18
+ const key = result.content.trim().toLowerCase();
19
+ const existing = seen.get(key);
20
+ if (!existing || result.score > existing.score) {
21
+ seen.set(key, result);
22
+ }
23
+ }
24
+ return Array.from(seen.values()).sort((a, b) => b.score - a.score);
25
+ }
26
+ /**
27
+ * Rerank results by keyword overlap with the query.
28
+ * Combines original score with keyword overlap boost.
29
+ */
30
+ export function rerankByKeywordOverlap(results, query) {
31
+ const queryTokens = new Set(tokenize(query));
32
+ if (queryTokens.size === 0)
33
+ return results;
34
+ const scored = results.map((r) => {
35
+ const contentTokens = tokenize(r.content);
36
+ const overlap = contentTokens.filter((t) => queryTokens.has(t)).length;
37
+ const overlapRatio = contentTokens.length > 0 ? overlap / queryTokens.size : 0;
38
+ // Combine: 70% original score + 30% keyword overlap
39
+ const combinedScore = r.score * 0.7 + overlapRatio * 0.3;
40
+ return { ...r, score: Math.round(combinedScore * 10000) / 10000 };
41
+ });
42
+ return scored.sort((a, b) => b.score - a.score);
43
+ }
44
+ /**
45
+ * Merge adjacent chunks from the same source document.
46
+ * Chunks are considered adjacent if their chunk indices differ by 1.
47
+ */
48
+ export function stitchAdjacentChunks(results, chunkMeta) {
49
+ if (results.length <= 1 || chunkMeta.size === 0)
50
+ return results;
51
+ // Group by sourceId
52
+ const groups = new Map();
53
+ const ungrouped = [];
54
+ for (const r of results) {
55
+ const chunkIdx = chunkMeta.get(r.id);
56
+ if (chunkIdx === undefined) {
57
+ ungrouped.push(r);
58
+ continue;
59
+ }
60
+ const group = groups.get(r.sourceId) ?? [];
61
+ group.push(r);
62
+ groups.set(r.sourceId, group);
63
+ }
64
+ const stitched = [];
65
+ for (const [_sourceId, group] of groups) {
66
+ // Sort by chunk index
67
+ group.sort((a, b) => (chunkMeta.get(a.id) ?? 0) - (chunkMeta.get(b.id) ?? 0));
68
+ let current = group[0];
69
+ let currentIdx = chunkMeta.get(current.id) ?? 0;
70
+ for (let i = 1; i < group.length; i++) {
71
+ const next = group[i];
72
+ const nextIdx = chunkMeta.get(next.id) ?? 0;
73
+ if (nextIdx === currentIdx + 1) {
74
+ // Stitch: merge content, keep higher score
75
+ current = {
76
+ ...current,
77
+ content: current.content + "\n\n" + next.content,
78
+ score: Math.max(current.score, next.score),
79
+ strategies: [...new Set([...current.strategies, ...next.strategies])],
80
+ };
81
+ currentIdx = nextIdx;
82
+ }
83
+ else {
84
+ stitched.push(current);
85
+ current = next;
86
+ currentIdx = nextIdx;
87
+ }
88
+ }
89
+ stitched.push(current);
90
+ }
91
+ const final = [...stitched, ...ungrouped].sort((a, b) => b.score - a.score);
92
+ return final;
93
+ }
94
+ /**
95
+ * Full post-retrieval pipeline.
96
+ */
97
+ export function postRetrievalPipeline(options) {
98
+ const { query, results, maxResults, chunkMeta } = options;
99
+ // Stage 1: Deduplication
100
+ const deduped = deduplicateResults(results);
101
+ const deduplicated = results.length - deduped.length;
102
+ // Stage 2: Reranking
103
+ const reranked = rerankByKeywordOverlap(deduped, query);
104
+ // Stage 3: Chunk stitching (if metadata available)
105
+ const stitched = chunkMeta
106
+ ? stitchAdjacentChunks(reranked, chunkMeta)
107
+ : reranked;
108
+ const stitchedChunks = reranked.length - stitched.length;
109
+ // Stage 4: Limit
110
+ const limited = stitched.slice(0, maxResults);
111
+ logger.debug("Post-retrieval pipeline complete", {
112
+ input: results.length,
113
+ deduplicated,
114
+ stitchedChunks,
115
+ output: limited.length,
116
+ });
117
+ return { results: limited, deduplicated, stitchedChunks };
118
+ }
119
+ //# sourceMappingURL=post-retrieval.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post-retrieval.js","sourceRoot":"","sources":["../../../src/core/rag/post-retrieval.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Query Cache — in-memory cache for RAG search results.
3
+ *
4
+ * Features:
5
+ * - TTL-based expiration
6
+ * - LRU eviction when maxSize exceeded
7
+ * - Query normalization (case-insensitive, trimmed)
8
+ * - Hit/miss statistics
9
+ * - Bulk invalidation (e.g., when knowledge store changes)
10
+ */
11
+ import type { RankedResult } from "./multi-strategy-retrieval.js";
12
+ export interface CacheOptions {
13
+ ttlMs: number;
14
+ maxSize: number;
15
+ }
16
+ export interface CacheStats {
17
+ size: number;
18
+ hits: number;
19
+ misses: number;
20
+ evictions: number;
21
+ }
22
+ /**
23
+ * In-memory query cache with TTL and LRU eviction.
24
+ */
25
+ export declare class QueryCache {
26
+ private entries;
27
+ private ttlMs;
28
+ private maxSize;
29
+ private hits;
30
+ private misses;
31
+ private evictions;
32
+ constructor(options: CacheOptions);
33
+ /**
34
+ * Retrieve cached results for a query, or undefined if miss/expired.
35
+ */
36
+ get(query: string): RankedResult[] | undefined;
37
+ /**
38
+ * Store results for a query.
39
+ */
40
+ set(query: string, results: RankedResult[]): void;
41
+ /**
42
+ * Invalidate all cached entries.
43
+ */
44
+ invalidateAll(): void;
45
+ /**
46
+ * Get cache statistics.
47
+ */
48
+ getStats(): CacheStats;
49
+ /**
50
+ * Evict the oldest (by creation time) entry.
51
+ */
52
+ private evictOldest;
53
+ }
54
+ //# sourceMappingURL=query-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-cache.d.ts","sourceRoot":"","sources":["../../../src/core/rag/query-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAGlE,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAQD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AASD;;GAEG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,OAAO,CAAsC;IACrD,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,SAAS,CAAa;gBAElB,OAAO,EAAE,YAAY;IAKjC;;OAEG;IACH,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,EAAE,GAAG,SAAS;IAqB9C;;OAEG;IACH,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,IAAI;IAejD;;OAEG;IACH,aAAa,IAAI,IAAI;IAMrB;;OAEG;IACH,QAAQ,IAAI,UAAU;IAStB;;OAEG;IACH,OAAO,CAAC,WAAW;CAgBpB"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Query Cache — in-memory cache for RAG search results.
3
+ *
4
+ * Features:
5
+ * - TTL-based expiration
6
+ * - LRU eviction when maxSize exceeded
7
+ * - Query normalization (case-insensitive, trimmed)
8
+ * - Hit/miss statistics
9
+ * - Bulk invalidation (e.g., when knowledge store changes)
10
+ */
11
+ import { logger } from "../utils/logger.js";
12
+ /**
13
+ * Normalize query for consistent cache keys.
14
+ */
15
+ function normalizeKey(query) {
16
+ return query.trim().toLowerCase();
17
+ }
18
+ /**
19
+ * In-memory query cache with TTL and LRU eviction.
20
+ */
21
+ export class QueryCache {
22
+ entries = new Map();
23
+ ttlMs;
24
+ maxSize;
25
+ hits = 0;
26
+ misses = 0;
27
+ evictions = 0;
28
+ constructor(options) {
29
+ this.ttlMs = options.ttlMs;
30
+ this.maxSize = options.maxSize;
31
+ }
32
+ /**
33
+ * Retrieve cached results for a query, or undefined if miss/expired.
34
+ */
35
+ get(query) {
36
+ const key = normalizeKey(query);
37
+ const entry = this.entries.get(key);
38
+ if (!entry) {
39
+ this.misses++;
40
+ return undefined;
41
+ }
42
+ // Check TTL
43
+ if (Date.now() - entry.createdAt > this.ttlMs) {
44
+ this.entries.delete(key);
45
+ this.misses++;
46
+ return undefined;
47
+ }
48
+ entry.lastAccessedAt = Date.now();
49
+ this.hits++;
50
+ return entry.results;
51
+ }
52
+ /**
53
+ * Store results for a query.
54
+ */
55
+ set(query, results) {
56
+ const key = normalizeKey(query);
57
+ // Evict if at capacity
58
+ if (this.entries.size >= this.maxSize && !this.entries.has(key)) {
59
+ this.evictOldest();
60
+ }
61
+ this.entries.set(key, {
62
+ results,
63
+ createdAt: Date.now(),
64
+ lastAccessedAt: Date.now(),
65
+ });
66
+ }
67
+ /**
68
+ * Invalidate all cached entries.
69
+ */
70
+ invalidateAll() {
71
+ const count = this.entries.size;
72
+ this.entries.clear();
73
+ logger.debug("Query cache invalidated", { entriesCleared: count });
74
+ }
75
+ /**
76
+ * Get cache statistics.
77
+ */
78
+ getStats() {
79
+ return {
80
+ size: this.entries.size,
81
+ hits: this.hits,
82
+ misses: this.misses,
83
+ evictions: this.evictions,
84
+ };
85
+ }
86
+ /**
87
+ * Evict the oldest (by creation time) entry.
88
+ */
89
+ evictOldest() {
90
+ let oldestKey;
91
+ let oldestTime = Infinity;
92
+ for (const [key, entry] of this.entries) {
93
+ if (entry.createdAt < oldestTime) {
94
+ oldestTime = entry.createdAt;
95
+ oldestKey = key;
96
+ }
97
+ }
98
+ if (oldestKey) {
99
+ this.entries.delete(oldestKey);
100
+ this.evictions++;
101
+ }
102
+ }
103
+ }
104
+ //# sourceMappingURL=query-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-cache.js","sourceRoot":"","sources":["../../../src/core/rag/query-cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Query Understanding — preprocesses user queries before retrieval.
3
+ *
4
+ * Provides:
5
+ * - Intent detection (search, how_to, status, debug, compare, history)
6
+ * - Entity extraction (PascalCase, camelCase from query)
7
+ * - Source type filtering (detect "in the PRD", "in code", etc.)
8
+ * - Query expansion with related terms
9
+ * - Query rewriting for FTS5 optimization
10
+ */
11
+ export type QueryIntent = "search" | "how_to" | "status" | "debug" | "compare" | "history";
12
+ export interface UnderstandingResult {
13
+ originalQuery: string;
14
+ rewrittenQuery: string;
15
+ entities: string[];
16
+ intent: QueryIntent;
17
+ expandedTerms: string[];
18
+ sourceTypeFilter: string[];
19
+ }
20
+ /**
21
+ * Detect the intent of a query from keyword patterns.
22
+ */
23
+ export declare function detectIntent(query: string): QueryIntent;
24
+ /**
25
+ * Detect source type filters from query content.
26
+ */
27
+ export declare function detectSourceFilter(query: string): string[];
28
+ /**
29
+ * Expand query tokens with related technical terms.
30
+ */
31
+ export declare function expandQuery(query: string): string[];
32
+ /**
33
+ * Full query understanding pipeline.
34
+ * Analyzes a natural language query and returns structured understanding.
35
+ */
36
+ export declare function understandQuery(query: string): UnderstandingResult;
37
+ //# sourceMappingURL=query-understanding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-understanding.d.ts","sourceRoot":"","sources":["../../../src/core/rag/query-understanding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;AAE3F,MAAM,WAAW,mBAAmB;IAClC,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,EAAE,WAAW,CAAC;IACpB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B;AAYD;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAKvD;AAiBD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAQ1D;AAmBD;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAYnD;AAUD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,mBAAmB,CAuBlE"}