@danielsimonjr/memory-mcp 9.8.3 → 9.9.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/README.md +360 -1829
- package/dist/core/ManagerContext.d.ts +4 -0
- package/dist/core/ManagerContext.d.ts.map +1 -1
- package/dist/core/ManagerContext.js +6 -0
- package/dist/features/KeywordExtractor.d.ts +61 -0
- package/dist/features/KeywordExtractor.d.ts.map +1 -0
- package/dist/features/KeywordExtractor.js +126 -0
- package/dist/features/ObservationNormalizer.d.ts +90 -0
- package/dist/features/ObservationNormalizer.d.ts.map +1 -0
- package/dist/features/ObservationNormalizer.js +193 -0
- package/dist/features/index.d.ts +2 -0
- package/dist/features/index.d.ts.map +1 -1
- package/dist/features/index.js +3 -0
- package/dist/search/HybridSearchManager.d.ts +80 -0
- package/dist/search/HybridSearchManager.d.ts.map +1 -0
- package/dist/search/HybridSearchManager.js +187 -0
- package/dist/search/QueryAnalyzer.d.ts +76 -0
- package/dist/search/QueryAnalyzer.d.ts.map +1 -0
- package/dist/search/QueryAnalyzer.js +227 -0
- package/dist/search/QueryPlanner.d.ts +58 -0
- package/dist/search/QueryPlanner.d.ts.map +1 -0
- package/dist/search/QueryPlanner.js +137 -0
- package/dist/search/ReflectionManager.d.ts +71 -0
- package/dist/search/ReflectionManager.d.ts.map +1 -0
- package/dist/search/ReflectionManager.js +124 -0
- package/dist/search/SymbolicSearch.d.ts +61 -0
- package/dist/search/SymbolicSearch.d.ts.map +1 -0
- package/dist/search/SymbolicSearch.js +163 -0
- package/dist/search/index.d.ts +5 -0
- package/dist/search/index.d.ts.map +1 -1
- package/dist/search/index.js +8 -0
- package/dist/server/toolDefinitions.d.ts +1 -1
- package/dist/server/toolDefinitions.d.ts.map +1 -1
- package/dist/server/toolDefinitions.js +141 -1
- package/dist/server/toolHandlers.d.ts.map +1 -1
- package/dist/server/toolHandlers.js +167 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/types.d.ts +118 -0
- package/dist/types/types.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reflection Manager
|
|
3
|
+
*
|
|
4
|
+
* Phase 11: Implements reflection-based iterative retrieval
|
|
5
|
+
* that refines results until adequate.
|
|
6
|
+
*
|
|
7
|
+
* @module search/ReflectionManager
|
|
8
|
+
*/
|
|
9
|
+
import type { ReadonlyKnowledgeGraph, HybridSearchResult, HybridSearchOptions } from '../types/index.js';
|
|
10
|
+
import type { HybridSearchManager } from './HybridSearchManager.js';
|
|
11
|
+
import type { QueryAnalyzer } from './QueryAnalyzer.js';
|
|
12
|
+
/**
|
|
13
|
+
* Options for reflection-based retrieval.
|
|
14
|
+
*/
|
|
15
|
+
export interface ReflectionOptions {
|
|
16
|
+
/** Maximum number of reflection iterations (default: 3) */
|
|
17
|
+
maxIterations?: number;
|
|
18
|
+
/** Adequacy threshold 0-1 (default: 0.7) */
|
|
19
|
+
adequacyThreshold?: number;
|
|
20
|
+
/** Minimum results required (default: 3) */
|
|
21
|
+
minResults?: number;
|
|
22
|
+
/** Hybrid search options */
|
|
23
|
+
searchOptions?: Partial<HybridSearchOptions>;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Result of reflection-based retrieval.
|
|
27
|
+
*/
|
|
28
|
+
export interface ReflectionResult {
|
|
29
|
+
results: HybridSearchResult[];
|
|
30
|
+
iterations: number;
|
|
31
|
+
adequate: boolean;
|
|
32
|
+
refinements: string[];
|
|
33
|
+
adequacyScore: number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Reflection Manager for iterative retrieval refinement.
|
|
37
|
+
*
|
|
38
|
+
* Implements the SimpleMem-inspired reflection loop:
|
|
39
|
+
* 1. Execute initial search
|
|
40
|
+
* 2. Check result adequacy
|
|
41
|
+
* 3. If inadequate, refine query and repeat
|
|
42
|
+
* 4. Combine results from all iterations
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* const reflection = new ReflectionManager(hybridSearch, analyzer);
|
|
47
|
+
* const result = await reflection.retrieveWithReflection(
|
|
48
|
+
* graph,
|
|
49
|
+
* 'What projects did Alice work on?',
|
|
50
|
+
* { maxIterations: 3 }
|
|
51
|
+
* );
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export declare class ReflectionManager {
|
|
55
|
+
private hybridSearch;
|
|
56
|
+
private analyzer;
|
|
57
|
+
constructor(hybridSearch: HybridSearchManager, analyzer: QueryAnalyzer);
|
|
58
|
+
/**
|
|
59
|
+
* Perform retrieval with reflection-based refinement.
|
|
60
|
+
*/
|
|
61
|
+
retrieveWithReflection(graph: ReadonlyKnowledgeGraph, query: string, options?: ReflectionOptions): Promise<ReflectionResult>;
|
|
62
|
+
/**
|
|
63
|
+
* Calculate result adequacy score.
|
|
64
|
+
*/
|
|
65
|
+
private calculateAdequacy;
|
|
66
|
+
/**
|
|
67
|
+
* Refine query based on current results and analysis.
|
|
68
|
+
*/
|
|
69
|
+
private refineQuery;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=ReflectionManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ReflectionManager.d.ts","sourceRoot":"","sources":["../../src/search/ReflectionManager.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,sBAAsB,EAEtB,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,2DAA2D;IAC3D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,4CAA4C;IAC5C,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,4CAA4C;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4BAA4B;IAC5B,aAAa,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;CAC9C;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,iBAAiB;IAE1B,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,QAAQ;gBADR,YAAY,EAAE,mBAAmB,EACjC,QAAQ,EAAE,aAAa;IAGjC;;OAEG;IACG,sBAAsB,CAC1B,KAAK,EAAE,sBAAsB,EAC7B,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,gBAAgB,CAAC;IA2D5B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA6BzB;;OAEG;IACH,OAAO,CAAC,WAAW;CA6BpB"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reflection Manager
|
|
3
|
+
*
|
|
4
|
+
* Phase 11: Implements reflection-based iterative retrieval
|
|
5
|
+
* that refines results until adequate.
|
|
6
|
+
*
|
|
7
|
+
* @module search/ReflectionManager
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Reflection Manager for iterative retrieval refinement.
|
|
11
|
+
*
|
|
12
|
+
* Implements the SimpleMem-inspired reflection loop:
|
|
13
|
+
* 1. Execute initial search
|
|
14
|
+
* 2. Check result adequacy
|
|
15
|
+
* 3. If inadequate, refine query and repeat
|
|
16
|
+
* 4. Combine results from all iterations
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* const reflection = new ReflectionManager(hybridSearch, analyzer);
|
|
21
|
+
* const result = await reflection.retrieveWithReflection(
|
|
22
|
+
* graph,
|
|
23
|
+
* 'What projects did Alice work on?',
|
|
24
|
+
* { maxIterations: 3 }
|
|
25
|
+
* );
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export class ReflectionManager {
|
|
29
|
+
hybridSearch;
|
|
30
|
+
analyzer;
|
|
31
|
+
constructor(hybridSearch, analyzer) {
|
|
32
|
+
this.hybridSearch = hybridSearch;
|
|
33
|
+
this.analyzer = analyzer;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Perform retrieval with reflection-based refinement.
|
|
37
|
+
*/
|
|
38
|
+
async retrieveWithReflection(graph, query, options = {}) {
|
|
39
|
+
const { maxIterations = 3, adequacyThreshold = 0.7, minResults = 3, searchOptions = {}, } = options;
|
|
40
|
+
const allResults = [];
|
|
41
|
+
const refinements = [];
|
|
42
|
+
let currentQuery = query;
|
|
43
|
+
let iteration = 0;
|
|
44
|
+
let adequacyScore = 0;
|
|
45
|
+
while (iteration < maxIterations) {
|
|
46
|
+
iteration++;
|
|
47
|
+
// Execute search
|
|
48
|
+
const results = await this.hybridSearch.searchWithEntities(graph, currentQuery, searchOptions);
|
|
49
|
+
// Add new results (deduplicated)
|
|
50
|
+
for (const result of results) {
|
|
51
|
+
if (!allResults.some(r => r.entity.name === result.entity.name)) {
|
|
52
|
+
allResults.push(result);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// Check adequacy
|
|
56
|
+
const analysis = this.analyzer.analyze(query);
|
|
57
|
+
adequacyScore = this.calculateAdequacy(allResults, analysis, minResults);
|
|
58
|
+
if (adequacyScore >= adequacyThreshold) {
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
// Refine query if not adequate
|
|
62
|
+
const refinedQuery = this.refineQuery(currentQuery, allResults, analysis);
|
|
63
|
+
if (refinedQuery === currentQuery) {
|
|
64
|
+
// No refinement possible
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
refinements.push(refinedQuery);
|
|
68
|
+
currentQuery = refinedQuery;
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
results: allResults.sort((a, b) => b.scores.combined - a.scores.combined),
|
|
72
|
+
iterations: iteration,
|
|
73
|
+
adequate: adequacyScore >= adequacyThreshold,
|
|
74
|
+
refinements,
|
|
75
|
+
adequacyScore,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Calculate result adequacy score.
|
|
80
|
+
*/
|
|
81
|
+
calculateAdequacy(results, analysis, minResults) {
|
|
82
|
+
let score = 0;
|
|
83
|
+
const weights = { quantity: 0.4, diversity: 0.3, relevance: 0.3 };
|
|
84
|
+
// Quantity: Do we have enough results?
|
|
85
|
+
const quantityScore = Math.min(results.length / minResults, 1);
|
|
86
|
+
score += quantityScore * weights.quantity;
|
|
87
|
+
// Diversity: Do results cover different entity types?
|
|
88
|
+
const types = new Set(results.map(r => r.entity.entityType));
|
|
89
|
+
const diversityScore = Math.min(types.size / 3, 1);
|
|
90
|
+
score += diversityScore * weights.diversity;
|
|
91
|
+
// Relevance: Average combined score
|
|
92
|
+
const avgScore = results.length > 0
|
|
93
|
+
? results.reduce((sum, r) => sum + r.scores.combined, 0) / results.length
|
|
94
|
+
: 0;
|
|
95
|
+
score += avgScore * weights.relevance;
|
|
96
|
+
// Suppress unused parameter warning - analysis reserved for future enhancements
|
|
97
|
+
void analysis;
|
|
98
|
+
return score;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Refine query based on current results and analysis.
|
|
102
|
+
*/
|
|
103
|
+
refineQuery(query, results, analysis) {
|
|
104
|
+
// Check what information types are missing
|
|
105
|
+
const coveredTypes = new Set();
|
|
106
|
+
for (const result of results) {
|
|
107
|
+
coveredTypes.add(result.entity.entityType.toLowerCase());
|
|
108
|
+
}
|
|
109
|
+
// If looking for persons but no person results, refine
|
|
110
|
+
if (analysis.requiredInfoTypes.includes('person') && !coveredTypes.has('person')) {
|
|
111
|
+
return `${query} person people`;
|
|
112
|
+
}
|
|
113
|
+
// If temporal query but no temporal context, add time hint
|
|
114
|
+
if (analysis.temporalRange && results.length < 3) {
|
|
115
|
+
return `${query} recent history timeline`;
|
|
116
|
+
}
|
|
117
|
+
// Broaden query by removing constraints
|
|
118
|
+
const broader = query.replace(/\b(only|just|exactly|specific)\b/gi, '');
|
|
119
|
+
if (broader !== query) {
|
|
120
|
+
return broader.trim();
|
|
121
|
+
}
|
|
122
|
+
return query;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Symbolic Search Layer
|
|
3
|
+
*
|
|
4
|
+
* Phase 11: Provides metadata-based filtering using structured predicates.
|
|
5
|
+
* Part of the three-layer hybrid search architecture.
|
|
6
|
+
*
|
|
7
|
+
* @module search/SymbolicSearch
|
|
8
|
+
*/
|
|
9
|
+
import type { Entity, SymbolicFilters } from '../types/index.js';
|
|
10
|
+
/**
|
|
11
|
+
* Result from symbolic search with match score.
|
|
12
|
+
*/
|
|
13
|
+
export interface SymbolicResult {
|
|
14
|
+
entity: Entity;
|
|
15
|
+
score: number;
|
|
16
|
+
matchedFilters: string[];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Symbolic Search provides metadata-based filtering.
|
|
20
|
+
*
|
|
21
|
+
* Filters entities using structured predicates on tags, types,
|
|
22
|
+
* dates, importance, and hierarchy.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* const symbolic = new SymbolicSearch();
|
|
27
|
+
* const results = symbolic.search(entities, {
|
|
28
|
+
* tags: ['important'],
|
|
29
|
+
* entityTypes: ['person'],
|
|
30
|
+
* importance: { min: 5 }
|
|
31
|
+
* });
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare class SymbolicSearch {
|
|
35
|
+
/**
|
|
36
|
+
* Filter entities using structured metadata predicates.
|
|
37
|
+
* All filters are AND-combined.
|
|
38
|
+
*
|
|
39
|
+
* @param entities - Entities to filter
|
|
40
|
+
* @param filters - Symbolic filter criteria
|
|
41
|
+
* @returns Filtered entities with match scores
|
|
42
|
+
*/
|
|
43
|
+
search(entities: readonly Entity[], filters: SymbolicFilters): SymbolicResult[];
|
|
44
|
+
/**
|
|
45
|
+
* Evaluate all filters against an entity.
|
|
46
|
+
*/
|
|
47
|
+
private evaluateFilters;
|
|
48
|
+
/**
|
|
49
|
+
* Get entities matching a specific tag.
|
|
50
|
+
*/
|
|
51
|
+
byTag(entities: readonly Entity[], tag: string): Entity[];
|
|
52
|
+
/**
|
|
53
|
+
* Get entities of a specific type.
|
|
54
|
+
*/
|
|
55
|
+
byType(entities: readonly Entity[], entityType: string): Entity[];
|
|
56
|
+
/**
|
|
57
|
+
* Get entities within importance range.
|
|
58
|
+
*/
|
|
59
|
+
byImportance(entities: readonly Entity[], min: number, max: number): Entity[];
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=SymbolicSearch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SymbolicSearch.d.ts","sourceRoot":"","sources":["../../src/search/SymbolicSearch.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEjE;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,cAAc;IACzB;;;;;;;OAOG;IACH,MAAM,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,eAAe,GAAG,cAAc,EAAE;IAc/E;;OAEG;IACH,OAAO,CAAC,eAAe;IAyGvB;;OAEG;IACH,KAAK,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE;IAMzD;;OAEG;IACH,MAAM,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE;IAMjE;;OAEG;IACH,YAAY,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE;CAM9E"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Symbolic Search Layer
|
|
3
|
+
*
|
|
4
|
+
* Phase 11: Provides metadata-based filtering using structured predicates.
|
|
5
|
+
* Part of the three-layer hybrid search architecture.
|
|
6
|
+
*
|
|
7
|
+
* @module search/SymbolicSearch
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Symbolic Search provides metadata-based filtering.
|
|
11
|
+
*
|
|
12
|
+
* Filters entities using structured predicates on tags, types,
|
|
13
|
+
* dates, importance, and hierarchy.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* const symbolic = new SymbolicSearch();
|
|
18
|
+
* const results = symbolic.search(entities, {
|
|
19
|
+
* tags: ['important'],
|
|
20
|
+
* entityTypes: ['person'],
|
|
21
|
+
* importance: { min: 5 }
|
|
22
|
+
* });
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export class SymbolicSearch {
|
|
26
|
+
/**
|
|
27
|
+
* Filter entities using structured metadata predicates.
|
|
28
|
+
* All filters are AND-combined.
|
|
29
|
+
*
|
|
30
|
+
* @param entities - Entities to filter
|
|
31
|
+
* @param filters - Symbolic filter criteria
|
|
32
|
+
* @returns Filtered entities with match scores
|
|
33
|
+
*/
|
|
34
|
+
search(entities, filters) {
|
|
35
|
+
const results = [];
|
|
36
|
+
for (const entity of entities) {
|
|
37
|
+
const { matches, score, matchedFilters } = this.evaluateFilters(entity, filters);
|
|
38
|
+
if (matches) {
|
|
39
|
+
results.push({ entity, score, matchedFilters });
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// Sort by score descending
|
|
43
|
+
return results.sort((a, b) => b.score - a.score);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Evaluate all filters against an entity.
|
|
47
|
+
*/
|
|
48
|
+
evaluateFilters(entity, filters) {
|
|
49
|
+
const matchedFilters = [];
|
|
50
|
+
let totalFilters = 0;
|
|
51
|
+
let matchedCount = 0;
|
|
52
|
+
// Tag filter
|
|
53
|
+
if (filters.tags && filters.tags.length > 0) {
|
|
54
|
+
totalFilters++;
|
|
55
|
+
const entityTags = entity.tags ?? [];
|
|
56
|
+
const matchingTags = filters.tags.filter((t) => entityTags.some((et) => et.toLowerCase() === t.toLowerCase()));
|
|
57
|
+
if (matchingTags.length > 0) {
|
|
58
|
+
matchedCount++;
|
|
59
|
+
matchedFilters.push(`tags:${matchingTags.join(',')}`);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
return { matches: false, score: 0, matchedFilters: [] };
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// Entity type filter
|
|
66
|
+
if (filters.entityTypes && filters.entityTypes.length > 0) {
|
|
67
|
+
totalFilters++;
|
|
68
|
+
if (filters.entityTypes.some((t) => t.toLowerCase() === entity.entityType.toLowerCase())) {
|
|
69
|
+
matchedCount++;
|
|
70
|
+
matchedFilters.push(`type:${entity.entityType}`);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
return { matches: false, score: 0, matchedFilters: [] };
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// Date range filter
|
|
77
|
+
if (filters.dateRange) {
|
|
78
|
+
totalFilters++;
|
|
79
|
+
const entityDate = entity.createdAt || entity.lastModified;
|
|
80
|
+
if (!entityDate) {
|
|
81
|
+
// Entities without dates are excluded when date filter is applied
|
|
82
|
+
return { matches: false, score: 0, matchedFilters: [] };
|
|
83
|
+
}
|
|
84
|
+
const date = new Date(entityDate);
|
|
85
|
+
const start = filters.dateRange.start ? new Date(filters.dateRange.start) : null;
|
|
86
|
+
const end = filters.dateRange.end ? new Date(filters.dateRange.end) : null;
|
|
87
|
+
const inRange = (!start || date >= start) && (!end || date <= end);
|
|
88
|
+
if (inRange) {
|
|
89
|
+
matchedCount++;
|
|
90
|
+
matchedFilters.push('dateRange');
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
return { matches: false, score: 0, matchedFilters: [] };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// Importance filter
|
|
97
|
+
if (filters.importance) {
|
|
98
|
+
totalFilters++;
|
|
99
|
+
const importance = entity.importance ?? 5;
|
|
100
|
+
const { min, max } = filters.importance;
|
|
101
|
+
const inRange = (min === undefined || importance >= min) &&
|
|
102
|
+
(max === undefined || importance <= max);
|
|
103
|
+
if (inRange) {
|
|
104
|
+
matchedCount++;
|
|
105
|
+
matchedFilters.push(`importance:${importance}`);
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
return { matches: false, score: 0, matchedFilters: [] };
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// Parent filter
|
|
112
|
+
if (filters.parentId !== undefined) {
|
|
113
|
+
totalFilters++;
|
|
114
|
+
if (entity.parentId === filters.parentId) {
|
|
115
|
+
matchedCount++;
|
|
116
|
+
matchedFilters.push(`parent:${filters.parentId}`);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
return { matches: false, score: 0, matchedFilters: [] };
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// Has observations filter
|
|
123
|
+
if (filters.hasObservations !== undefined) {
|
|
124
|
+
totalFilters++;
|
|
125
|
+
const hasObs = entity.observations.length > 0;
|
|
126
|
+
if (hasObs === filters.hasObservations) {
|
|
127
|
+
matchedCount++;
|
|
128
|
+
matchedFilters.push('hasObservations');
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
return { matches: false, score: 0, matchedFilters: [] };
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
// If no filters specified, match all with base score
|
|
135
|
+
if (totalFilters === 0) {
|
|
136
|
+
return { matches: true, score: 0.5, matchedFilters: [] };
|
|
137
|
+
}
|
|
138
|
+
// Score based on proportion of filters matched
|
|
139
|
+
const score = matchedCount / totalFilters;
|
|
140
|
+
return { matches: true, score, matchedFilters };
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Get entities matching a specific tag.
|
|
144
|
+
*/
|
|
145
|
+
byTag(entities, tag) {
|
|
146
|
+
return entities.filter(e => e.tags?.some(t => t.toLowerCase() === tag.toLowerCase()));
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Get entities of a specific type.
|
|
150
|
+
*/
|
|
151
|
+
byType(entities, entityType) {
|
|
152
|
+
return entities.filter(e => e.entityType.toLowerCase() === entityType.toLowerCase());
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Get entities within importance range.
|
|
156
|
+
*/
|
|
157
|
+
byImportance(entities, min, max) {
|
|
158
|
+
return entities.filter(e => {
|
|
159
|
+
const imp = e.importance ?? 5;
|
|
160
|
+
return imp >= min && imp <= max;
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}
|
package/dist/search/index.d.ts
CHANGED
|
@@ -18,4 +18,9 @@ export { SemanticSearch, entityToText, } from './SemanticSearch.js';
|
|
|
18
18
|
export { TFIDFIndexManager } from './TFIDFIndexManager.js';
|
|
19
19
|
export { TFIDFEventSync } from './TFIDFEventSync.js';
|
|
20
20
|
export { QueryCostEstimator } from './QueryCostEstimator.js';
|
|
21
|
+
export { SymbolicSearch, type SymbolicResult } from './SymbolicSearch.js';
|
|
22
|
+
export { HybridSearchManager, DEFAULT_HYBRID_WEIGHTS } from './HybridSearchManager.js';
|
|
23
|
+
export { QueryAnalyzer } from './QueryAnalyzer.js';
|
|
24
|
+
export { QueryPlanner } from './QueryPlanner.js';
|
|
25
|
+
export { ReflectionManager, type ReflectionOptions, type ReflectionResult, } from './ReflectionManager.js';
|
|
21
26
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/search/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGnD,OAAO,EAAE,iBAAiB,EAAE,KAAK,aAAa,EAAE,KAAK,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAGzG,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,KAAK,2BAA2B,GACjC,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,cAAc,EACd,YAAY,GACb,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAGrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/search/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGnD,OAAO,EAAE,iBAAiB,EAAE,KAAK,aAAa,EAAE,KAAK,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAGzG,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,KAAK,2BAA2B,GACjC,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,cAAc,EACd,YAAY,GACb,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAGrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAG7D,OAAO,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAGvF,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGjD,OAAO,EACL,iBAAiB,EACjB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,GACtB,MAAM,wBAAwB,CAAC"}
|
package/dist/search/index.js
CHANGED
|
@@ -24,3 +24,11 @@ export { TFIDFIndexManager } from './TFIDFIndexManager.js';
|
|
|
24
24
|
export { TFIDFEventSync } from './TFIDFEventSync.js';
|
|
25
25
|
// Phase 10 Sprint 4: Query Cost Estimation
|
|
26
26
|
export { QueryCostEstimator } from './QueryCostEstimator.js';
|
|
27
|
+
// Phase 11 Sprint 1: Hybrid Search
|
|
28
|
+
export { SymbolicSearch } from './SymbolicSearch.js';
|
|
29
|
+
export { HybridSearchManager, DEFAULT_HYBRID_WEIGHTS } from './HybridSearchManager.js';
|
|
30
|
+
// Phase 11 Sprint 3: Query Analysis
|
|
31
|
+
export { QueryAnalyzer } from './QueryAnalyzer.js';
|
|
32
|
+
export { QueryPlanner } from './QueryPlanner.js';
|
|
33
|
+
// Phase 11 Sprint 4: Reflection-based Retrieval
|
|
34
|
+
export { ReflectionManager, } from './ReflectionManager.js';
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* MCP Tool Definitions
|
|
3
3
|
*
|
|
4
4
|
* Extracted from MCPServer.ts to reduce file size and improve maintainability.
|
|
5
|
-
* Contains all
|
|
5
|
+
* Contains all 59 tool schemas for the Knowledge Graph MCP Server.
|
|
6
6
|
*
|
|
7
7
|
* @module server/toolDefinitions
|
|
8
8
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toolDefinitions.d.ts","sourceRoot":"","sources":["../../src/server/toolDefinitions.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ,CAAC;QACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACpC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QACpB,oBAAoB,CAAC,EAAE,OAAO,CAAC;KAChC,CAAC;CACH;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"toolDefinitions.d.ts","sourceRoot":"","sources":["../../src/server/toolDefinitions.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ,CAAC;QACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACpC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QACpB,oBAAoB,CAAC,EAAE,OAAO,CAAC;KAChC,CAAC;CACH;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,cAAc,EAygC3C,CAAC"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* MCP Tool Definitions
|
|
3
3
|
*
|
|
4
4
|
* Extracted from MCPServer.ts to reduce file size and improve maintainability.
|
|
5
|
-
* Contains all
|
|
5
|
+
* Contains all 59 tool schemas for the Knowledge Graph MCP Server.
|
|
6
6
|
*
|
|
7
7
|
* @module server/toolDefinitions
|
|
8
8
|
*/
|
|
@@ -186,6 +186,34 @@ export const toolDefinitions = [
|
|
|
186
186
|
additionalProperties: false,
|
|
187
187
|
},
|
|
188
188
|
},
|
|
189
|
+
// Phase 11 Sprint 5: Observation Normalization
|
|
190
|
+
{
|
|
191
|
+
name: 'normalize_observations',
|
|
192
|
+
description: 'Normalize entity observations by resolving pronouns and anchoring relative dates. Improves search matching quality.',
|
|
193
|
+
inputSchema: {
|
|
194
|
+
type: 'object',
|
|
195
|
+
properties: {
|
|
196
|
+
entityName: {
|
|
197
|
+
type: 'string',
|
|
198
|
+
description: 'Entity name to normalize (omit for all entities)',
|
|
199
|
+
},
|
|
200
|
+
options: {
|
|
201
|
+
type: 'object',
|
|
202
|
+
properties: {
|
|
203
|
+
resolveCoreferences: { type: 'boolean', default: true },
|
|
204
|
+
anchorTimestamps: { type: 'boolean', default: true },
|
|
205
|
+
extractKeywords: { type: 'boolean', default: false },
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
persist: {
|
|
209
|
+
type: 'boolean',
|
|
210
|
+
default: false,
|
|
211
|
+
description: 'Save normalized observations to storage',
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
additionalProperties: false,
|
|
215
|
+
},
|
|
216
|
+
},
|
|
189
217
|
// ==================== SEARCH TOOLS ====================
|
|
190
218
|
{
|
|
191
219
|
name: 'search_nodes',
|
|
@@ -298,6 +326,118 @@ export const toolDefinitions = [
|
|
|
298
326
|
additionalProperties: false,
|
|
299
327
|
},
|
|
300
328
|
},
|
|
329
|
+
// Phase 11 Sprint 2: Hybrid Search
|
|
330
|
+
{
|
|
331
|
+
name: 'hybrid_search',
|
|
332
|
+
description: 'Search using combined semantic, lexical, and metadata signals. Provides better recall than single-signal search by fusing multiple relevance signals.',
|
|
333
|
+
inputSchema: {
|
|
334
|
+
type: 'object',
|
|
335
|
+
properties: {
|
|
336
|
+
query: {
|
|
337
|
+
type: 'string',
|
|
338
|
+
description: 'Search query text',
|
|
339
|
+
},
|
|
340
|
+
weights: {
|
|
341
|
+
type: 'object',
|
|
342
|
+
description: 'Layer weights (automatically normalized to sum to 1.0)',
|
|
343
|
+
properties: {
|
|
344
|
+
semantic: {
|
|
345
|
+
type: 'number',
|
|
346
|
+
description: 'Weight for semantic/embedding similarity (default: 0.5)',
|
|
347
|
+
},
|
|
348
|
+
lexical: {
|
|
349
|
+
type: 'number',
|
|
350
|
+
description: 'Weight for keyword/TF-IDF matching (default: 0.3)',
|
|
351
|
+
},
|
|
352
|
+
symbolic: {
|
|
353
|
+
type: 'number',
|
|
354
|
+
description: 'Weight for metadata filtering (default: 0.2)',
|
|
355
|
+
},
|
|
356
|
+
},
|
|
357
|
+
},
|
|
358
|
+
filters: {
|
|
359
|
+
type: 'object',
|
|
360
|
+
description: 'Symbolic/metadata filters',
|
|
361
|
+
properties: {
|
|
362
|
+
tags: {
|
|
363
|
+
type: 'array',
|
|
364
|
+
items: { type: 'string' },
|
|
365
|
+
description: 'Filter by tags',
|
|
366
|
+
},
|
|
367
|
+
entityTypes: {
|
|
368
|
+
type: 'array',
|
|
369
|
+
items: { type: 'string' },
|
|
370
|
+
description: 'Filter by entity types',
|
|
371
|
+
},
|
|
372
|
+
dateRange: {
|
|
373
|
+
type: 'object',
|
|
374
|
+
properties: {
|
|
375
|
+
start: { type: 'string', description: 'Start date (ISO 8601)' },
|
|
376
|
+
end: { type: 'string', description: 'End date (ISO 8601)' },
|
|
377
|
+
},
|
|
378
|
+
},
|
|
379
|
+
minImportance: { type: 'number', description: 'Minimum importance score (0-10)' },
|
|
380
|
+
maxImportance: { type: 'number', description: 'Maximum importance score (0-10)' },
|
|
381
|
+
},
|
|
382
|
+
},
|
|
383
|
+
limit: { type: 'number', description: 'Maximum results to return (default: 10)' },
|
|
384
|
+
},
|
|
385
|
+
required: ['query'],
|
|
386
|
+
additionalProperties: false,
|
|
387
|
+
},
|
|
388
|
+
},
|
|
389
|
+
// Phase 11 Sprint 3: Query Analysis
|
|
390
|
+
{
|
|
391
|
+
name: 'analyze_query',
|
|
392
|
+
description: 'Analyze a search query to extract entities, temporal references, question type, and complexity. Useful for understanding query structure before searching.',
|
|
393
|
+
inputSchema: {
|
|
394
|
+
type: 'object',
|
|
395
|
+
properties: {
|
|
396
|
+
query: {
|
|
397
|
+
type: 'string',
|
|
398
|
+
description: 'The query to analyze',
|
|
399
|
+
},
|
|
400
|
+
includePlan: {
|
|
401
|
+
type: 'boolean',
|
|
402
|
+
description: 'Include execution plan in response (default: false)',
|
|
403
|
+
},
|
|
404
|
+
},
|
|
405
|
+
required: ['query'],
|
|
406
|
+
additionalProperties: false,
|
|
407
|
+
},
|
|
408
|
+
},
|
|
409
|
+
// Phase 11 Sprint 4: Smart Search
|
|
410
|
+
{
|
|
411
|
+
name: 'smart_search',
|
|
412
|
+
description: 'Intelligent search with automatic query planning and reflection-based refinement. Iteratively improves results until adequate.',
|
|
413
|
+
inputSchema: {
|
|
414
|
+
type: 'object',
|
|
415
|
+
properties: {
|
|
416
|
+
query: {
|
|
417
|
+
type: 'string',
|
|
418
|
+
description: 'Search query text',
|
|
419
|
+
},
|
|
420
|
+
maxIterations: {
|
|
421
|
+
type: 'number',
|
|
422
|
+
description: 'Maximum reflection iterations (default: 3)',
|
|
423
|
+
},
|
|
424
|
+
adequacyThreshold: {
|
|
425
|
+
type: 'number',
|
|
426
|
+
description: 'Adequacy threshold 0-1 (default: 0.7)',
|
|
427
|
+
},
|
|
428
|
+
includePlan: {
|
|
429
|
+
type: 'boolean',
|
|
430
|
+
description: 'Include execution plan in response (default: true)',
|
|
431
|
+
},
|
|
432
|
+
limit: {
|
|
433
|
+
type: 'number',
|
|
434
|
+
description: 'Maximum results to return (default: 10)',
|
|
435
|
+
},
|
|
436
|
+
},
|
|
437
|
+
required: ['query'],
|
|
438
|
+
additionalProperties: false,
|
|
439
|
+
},
|
|
440
|
+
},
|
|
301
441
|
// ==================== SAVED SEARCH TOOLS ====================
|
|
302
442
|
{
|
|
303
443
|
name: 'save_search',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toolHandlers.d.ts","sourceRoot":"","sources":["../../src/server/toolHandlers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EACL,kBAAkB,EAmBnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"toolHandlers.d.ts","sourceRoot":"","sources":["../../src/server/toolHandlers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EACL,kBAAkB,EAmBnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAShE;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAEjE;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,CACxB,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC1B,OAAO,CAAC,YAAY,CAAC,CAAC;AAyC3B;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CA0tBpD,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,YAAY,CAAC,CAMvB"}
|