@pcircle/memesh 2.9.2 → 2.9.3

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 (122) hide show
  1. package/README.de.md +119 -78
  2. package/README.es.md +116 -75
  3. package/README.fr.md +116 -75
  4. package/README.id.md +115 -74
  5. package/README.ja.md +111 -70
  6. package/README.ko.md +116 -75
  7. package/README.md +113 -72
  8. package/README.th.md +118 -77
  9. package/README.vi.md +116 -75
  10. package/README.zh-CN.md +120 -79
  11. package/README.zh-TW.md +116 -75
  12. package/dist/core/GitCommandParser.d.ts +11 -0
  13. package/dist/core/GitCommandParser.d.ts.map +1 -0
  14. package/dist/core/GitCommandParser.js +43 -0
  15. package/dist/core/GitCommandParser.js.map +1 -0
  16. package/dist/core/HookIntegration.d.ts +0 -3
  17. package/dist/core/HookIntegration.d.ts.map +1 -1
  18. package/dist/core/HookIntegration.js +6 -30
  19. package/dist/core/HookIntegration.js.map +1 -1
  20. package/dist/embeddings/EmbeddingService.d.ts +3 -0
  21. package/dist/embeddings/EmbeddingService.d.ts.map +1 -1
  22. package/dist/embeddings/EmbeddingService.js +32 -6
  23. package/dist/embeddings/EmbeddingService.js.map +1 -1
  24. package/dist/embeddings/InMemoryVectorAdapter.d.ts +15 -0
  25. package/dist/embeddings/InMemoryVectorAdapter.d.ts.map +1 -0
  26. package/dist/embeddings/InMemoryVectorAdapter.js +58 -0
  27. package/dist/embeddings/InMemoryVectorAdapter.js.map +1 -0
  28. package/dist/embeddings/SqliteVecAdapter.d.ts +15 -0
  29. package/dist/embeddings/SqliteVecAdapter.d.ts.map +1 -0
  30. package/dist/embeddings/SqliteVecAdapter.js +107 -0
  31. package/dist/embeddings/SqliteVecAdapter.js.map +1 -0
  32. package/dist/embeddings/VectorExtension.d.ts +2 -4
  33. package/dist/embeddings/VectorExtension.d.ts.map +1 -1
  34. package/dist/embeddings/VectorExtension.js.map +1 -1
  35. package/dist/embeddings/VectorSearchAdapter.d.ts +17 -0
  36. package/dist/embeddings/VectorSearchAdapter.d.ts.map +1 -0
  37. package/dist/embeddings/VectorSearchAdapter.js +2 -0
  38. package/dist/embeddings/VectorSearchAdapter.js.map +1 -0
  39. package/dist/embeddings/index.d.ts +6 -1
  40. package/dist/embeddings/index.d.ts.map +1 -1
  41. package/dist/embeddings/index.js +4 -1
  42. package/dist/embeddings/index.js.map +1 -1
  43. package/dist/knowledge-graph/ContentHasher.d.ts +4 -0
  44. package/dist/knowledge-graph/ContentHasher.d.ts.map +1 -0
  45. package/dist/knowledge-graph/ContentHasher.js +8 -0
  46. package/dist/knowledge-graph/ContentHasher.js.map +1 -0
  47. package/dist/knowledge-graph/KGSearchEngine.d.ts +36 -0
  48. package/dist/knowledge-graph/KGSearchEngine.d.ts.map +1 -0
  49. package/dist/knowledge-graph/KGSearchEngine.js +257 -0
  50. package/dist/knowledge-graph/KGSearchEngine.js.map +1 -0
  51. package/dist/knowledge-graph/index.d.ts +18 -7
  52. package/dist/knowledge-graph/index.d.ts.map +1 -1
  53. package/dist/knowledge-graph/index.js +147 -242
  54. package/dist/knowledge-graph/index.js.map +1 -1
  55. package/dist/mcp/ServerInitializer.d.ts.map +1 -1
  56. package/dist/mcp/ServerInitializer.js +1 -1
  57. package/dist/mcp/ServerInitializer.js.map +1 -1
  58. package/dist/mcp/StdinBufferManager.d.ts +11 -0
  59. package/dist/mcp/StdinBufferManager.d.ts.map +1 -0
  60. package/dist/mcp/StdinBufferManager.js +62 -0
  61. package/dist/mcp/StdinBufferManager.js.map +1 -0
  62. package/dist/mcp/daemon/StdioProxyClient.d.ts.map +1 -1
  63. package/dist/mcp/daemon/StdioProxyClient.js +6 -0
  64. package/dist/mcp/daemon/StdioProxyClient.js.map +1 -1
  65. package/dist/mcp/handlers/HookToolHandler.d.ts +10 -0
  66. package/dist/mcp/handlers/HookToolHandler.d.ts.map +1 -0
  67. package/dist/mcp/handlers/HookToolHandler.js +92 -0
  68. package/dist/mcp/handlers/HookToolHandler.js.map +1 -0
  69. package/dist/mcp/handlers/MemoryToolHandler.d.ts +21 -0
  70. package/dist/mcp/handlers/MemoryToolHandler.d.ts.map +1 -0
  71. package/dist/mcp/handlers/MemoryToolHandler.js +430 -0
  72. package/dist/mcp/handlers/MemoryToolHandler.js.map +1 -0
  73. package/dist/mcp/handlers/SystemToolHandler.d.ts +14 -0
  74. package/dist/mcp/handlers/SystemToolHandler.d.ts.map +1 -0
  75. package/dist/mcp/handlers/SystemToolHandler.js +224 -0
  76. package/dist/mcp/handlers/SystemToolHandler.js.map +1 -0
  77. package/dist/mcp/handlers/ToolHandlers.d.ts +4 -17
  78. package/dist/mcp/handlers/ToolHandlers.d.ts.map +1 -1
  79. package/dist/mcp/handlers/ToolHandlers.js +19 -689
  80. package/dist/mcp/handlers/ToolHandlers.js.map +1 -1
  81. package/dist/mcp/handlers/index.d.ts +3 -0
  82. package/dist/mcp/handlers/index.d.ts.map +1 -1
  83. package/dist/mcp/handlers/index.js +3 -0
  84. package/dist/mcp/handlers/index.js.map +1 -1
  85. package/dist/mcp/server-bootstrap.js +24 -59
  86. package/dist/mcp/server-bootstrap.js.map +1 -1
  87. package/dist/mcp/tools/create-entities.d.ts.map +1 -1
  88. package/dist/mcp/tools/create-entities.js +18 -24
  89. package/dist/mcp/tools/create-entities.js.map +1 -1
  90. package/dist/memory/MemorySearchEngine.d.ts +17 -0
  91. package/dist/memory/MemorySearchEngine.d.ts.map +1 -0
  92. package/dist/memory/MemorySearchEngine.js +88 -0
  93. package/dist/memory/MemorySearchEngine.js.map +1 -0
  94. package/dist/memory/ProactiveRecaller.d.ts +26 -0
  95. package/dist/memory/ProactiveRecaller.d.ts.map +1 -0
  96. package/dist/memory/ProactiveRecaller.js +96 -0
  97. package/dist/memory/ProactiveRecaller.js.map +1 -0
  98. package/dist/memory/UnifiedMemoryStore.d.ts +1 -0
  99. package/dist/memory/UnifiedMemoryStore.d.ts.map +1 -1
  100. package/dist/memory/UnifiedMemoryStore.js +7 -63
  101. package/dist/memory/UnifiedMemoryStore.js.map +1 -1
  102. package/dist/memory/index.d.ts +3 -0
  103. package/dist/memory/index.d.ts.map +1 -1
  104. package/dist/memory/index.js +2 -0
  105. package/dist/memory/index.js.map +1 -1
  106. package/dist/utils/index.d.ts +0 -2
  107. package/dist/utils/index.d.ts.map +1 -1
  108. package/dist/utils/index.js +0 -2
  109. package/dist/utils/index.js.map +1 -1
  110. package/dist/utils/tracing/index.d.ts +0 -1
  111. package/dist/utils/tracing/index.d.ts.map +1 -1
  112. package/dist/utils/tracing/index.js +0 -1
  113. package/dist/utils/tracing/index.js.map +1 -1
  114. package/package.json +2 -11
  115. package/plugin.json +1 -1
  116. package/scripts/hooks/__tests__/post-tool-use-recall.test.js +192 -0
  117. package/scripts/hooks/__tests__/session-start-recall.test.js +86 -0
  118. package/scripts/hooks/post-tool-use-recall-utils.js +74 -0
  119. package/scripts/hooks/post-tool-use.js +79 -0
  120. package/scripts/hooks/session-start-recall-utils.js +40 -0
  121. package/scripts/hooks/session-start.js +66 -0
  122. package/scripts/hooks/templates/planning-template.md +46 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"KGSearchEngine.js","sourceRoot":"","sources":["../../src/knowledge-graph/KGSearchEngine.ts"],"names":[],"mappings":"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"}
@@ -1,15 +1,14 @@
1
1
  import type { Entity, Relation, SearchQuery, RelationTrace } from './types.js';
2
- export interface SemanticSearchResult {
3
- entity: Entity;
4
- similarity: number;
5
- }
2
+ import type { SemanticSearchResult } from './KGSearchEngine.js';
3
+ export type { SemanticSearchResult } from './KGSearchEngine.js';
6
4
  export declare class KnowledgeGraph {
7
5
  private db;
8
6
  private queryCache;
9
7
  private vectorEnabled;
10
- private vectorExt;
8
+ private vectorAdapter;
11
9
  private vectorInitPromise;
12
10
  private pendingEmbeddings;
11
+ private searchEngine;
13
12
  private constructor();
14
13
  private validateEntityName;
15
14
  private validateRelationType;
@@ -21,7 +20,19 @@ export declare class KnowledgeGraph {
21
20
  private escapeLikePattern;
22
21
  private searchFTS5;
23
22
  private prepareFTS5Query;
24
- createEntity(entity: Entity): string;
23
+ createEntity(entity: Entity, skipEmbedding?: boolean): string;
24
+ createEntitiesBatch(entities: Array<{
25
+ name: string;
26
+ entityType: string;
27
+ observations: string[];
28
+ tags?: string[];
29
+ metadata?: Record<string, unknown>;
30
+ contentHash?: string;
31
+ }>): Array<{
32
+ name: string;
33
+ success: boolean;
34
+ error?: string;
35
+ }>;
25
36
  createRelation(relation: Relation): void;
26
37
  searchEntities(query: SearchQuery): Entity[];
27
38
  getEntity(name: string): Entity | null;
@@ -33,6 +44,7 @@ export declare class KnowledgeGraph {
33
44
  };
34
45
  deleteEntity(name: string): boolean;
35
46
  private generateEmbeddingAsync;
47
+ private generateBatchEmbeddingsAsync;
36
48
  semanticSearch(query: string, options?: {
37
49
  limit?: number;
38
50
  minSimilarity?: number;
@@ -42,7 +54,6 @@ export declare class KnowledgeGraph {
42
54
  limit?: number;
43
55
  minSimilarity?: number;
44
56
  }): Promise<SemanticSearchResult[]>;
45
- private keywordSearchAsSemanticResults;
46
57
  isVectorSearchEnabled(): boolean;
47
58
  close(): Promise<void>;
48
59
  transaction<T>(fn: () => T): T;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/knowledge-graph/index.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAA4B,MAAM,YAAY,CAAC;AAazG,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAsBD,qBAAa,cAAc;IACzB,OAAO,CAAC,EAAE,CAAoB;IAC9B,OAAO,CAAC,UAAU,CAA0B;IAE5C,OAAO,CAAC,aAAa,CAAS;IAE9B,OAAO,CAAC,SAAS,CAAkF;IAEnG,OAAO,CAAC,iBAAiB,CAA8B;IAEvD,OAAO,CAAC,iBAAiB,CAAiC;IAK1D,OAAO;IAsBP,OAAO,CAAC,kBAAkB;IAsC1B,OAAO,CAAC,oBAAoB;WAgCf,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAqC7D,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,cAAc;IAyBlD,OAAO,CAAC,UAAU;IA+FlB,OAAO,CAAC,gBAAgB;IAyBxB,OAAO,CAAC,aAAa;IAuHrB,OAAO,CAAC,iBAAiB;IAqBzB,OAAO,CAAC,UAAU;IAyClB,OAAO,CAAC,gBAAgB;IAqExB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAmJpC,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IA8DxC,cAAc,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,EAAE;IA2J5C,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAuCtC,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU,GAAG,aAAa,GAAG,IAAI;IAkE3E,QAAQ,IAAI;QACV,aAAa,EAAE,MAAM,CAAC;QACtB,cAAc,EAAE,MAAM,CAAC;QACvB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACxC;IAgDD,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IA4DnC,OAAO,CAAC,sBAAsB;IA6BxB,cAAc,CAClB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;KAAO,GAC/E,OAAO,CAAC,oBAAoB,EAAE,CAAC;IA4C5B,YAAY,CAChB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAO,GACvD,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAwClC,OAAO,CAAC,8BAA8B;IAUtC,qBAAqB,IAAI,OAAO;IAQ1B,KAAK;IAoCX,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC;IAoB9B,aAAa;IAOb,UAAU;CAIX;AAGD,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/knowledge-graph/index.ts"],"names":[],"mappings":"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"}
@@ -6,16 +6,19 @@ import { QueryCache } from '../db/QueryCache.js';
6
6
  import { safeJsonParse, safeJsonStringify } from '../utils/json.js';
7
7
  import { getDataPath, getDataDirectory } from '../utils/PathResolver.js';
8
8
  import { validateNonEmptyString } from '../utils/validation.js';
9
+ import { KGSearchEngine } from './KGSearchEngine.js';
10
+ import { ContentHasher } from './ContentHasher.js';
9
11
  const MAX_ENTITY_NAME_LENGTH = 512;
10
12
  const VALID_RELATION_TYPE_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_-]*$/;
11
- const CONTROL_CHAR_PATTERN = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F\x80-\x9F]/;
13
+ import { CONTROL_CHAR_PATTERN } from './KGSearchEngine.js';
12
14
  export class KnowledgeGraph {
13
15
  db;
14
16
  queryCache;
15
17
  vectorEnabled = false;
16
- vectorExt = null;
18
+ vectorAdapter = null;
17
19
  vectorInitPromise = null;
18
20
  pendingEmbeddings = new Set();
21
+ searchEngine;
19
22
  constructor(_dbPath, db) {
20
23
  this.db = db;
21
24
  this.queryCache = new QueryCache({
@@ -23,6 +26,14 @@ export class KnowledgeGraph {
23
26
  defaultTTL: 5 * 60 * 1000,
24
27
  debug: false,
25
28
  });
29
+ this.searchEngine = new KGSearchEngine({
30
+ db: this.db,
31
+ getVectorAdapter: () => this.vectorAdapter,
32
+ isVectorEnabled: () => this.vectorEnabled,
33
+ getVectorInitPromise: () => this.vectorInitPromise,
34
+ getEntity: (name) => this.getEntity(name),
35
+ queryCache: this.queryCache,
36
+ });
26
37
  }
27
38
  validateEntityName(name) {
28
39
  validateNonEmptyString(name, 'Entity name');
@@ -154,15 +165,22 @@ export class KnowledgeGraph {
154
165
  );
155
166
  `;
156
167
  this.db.exec(fts5Schema);
168
+ this.db.exec(`
169
+ CREATE TABLE IF NOT EXISTS embedding_hashes (
170
+ entity_name TEXT PRIMARY KEY,
171
+ hash TEXT NOT NULL
172
+ );
173
+ `);
157
174
  this.runMigrations();
158
175
  this.initVectorSearch();
159
176
  }
160
177
  initVectorSearch() {
161
- this.vectorInitPromise = import('../embeddings/VectorExtension.js')
162
- .then(({ VectorExtension }) => {
163
- VectorExtension.loadExtension(this.db);
164
- VectorExtension.createVectorTable(this.db, 384);
165
- this.vectorExt = VectorExtension;
178
+ this.vectorInitPromise = import('../embeddings/SqliteVecAdapter.js')
179
+ .then(({ SqliteVecAdapter }) => {
180
+ const adapter = new SqliteVecAdapter();
181
+ adapter.loadExtension(this.db);
182
+ adapter.createVectorTable(this.db, 384);
183
+ this.vectorAdapter = adapter;
166
184
  this.vectorEnabled = true;
167
185
  logger.info('[KG] Vector search enabled (sqlite-vec loaded)');
168
186
  })
@@ -243,86 +261,15 @@ export class KnowledgeGraph {
243
261
  }
244
262
  }
245
263
  escapeLikePattern(pattern) {
246
- if (typeof pattern !== 'string') {
247
- throw new Error(`Pattern must be a string, got ${typeof pattern}`);
248
- }
249
- return pattern
250
- .replace(/!/g, '!!')
251
- .replace(/%/g, '!%')
252
- .replace(/_/g, '!_')
253
- .replace(/\[/g, '![')
254
- .replace(/\]/g, '!]');
264
+ return this.searchEngine.escapeLikePattern(pattern);
255
265
  }
256
266
  searchFTS5(query, limit) {
257
- if (!query || query.trim() === '') {
258
- return [];
259
- }
260
- const ftsQuery = this.prepareFTS5Query(query);
261
- if (!ftsQuery) {
262
- return [];
263
- }
264
- try {
265
- const results = this.db.prepare(`
266
- SELECT rowid, bm25(entities_fts, 10.0, 5.0) as rank
267
- FROM entities_fts
268
- WHERE entities_fts MATCH ?
269
- ORDER BY rank
270
- LIMIT ?
271
- `).all(ftsQuery, limit);
272
- return results.map(r => r.rowid);
273
- }
274
- catch (error) {
275
- logger.warn('[KG] FTS5 search failed, will use LIKE fallback:', {
276
- query,
277
- ftsQuery,
278
- error: error instanceof Error ? error.message : String(error)
279
- });
280
- return [];
281
- }
267
+ return this.searchEngine.searchFTS5(query, limit);
282
268
  }
283
269
  prepareFTS5Query(query) {
284
- const MAX_QUERY_LENGTH = 10000;
285
- const MAX_TOKENS = 100;
286
- let normalized = query.trim().replace(/\s+/g, ' ');
287
- if (!normalized) {
288
- return '';
289
- }
290
- if (normalized.length > MAX_QUERY_LENGTH) {
291
- logger.warn(`[KG] FTS5 query too long (${normalized.length} chars), truncating to ${MAX_QUERY_LENGTH}`);
292
- normalized = normalized.substring(0, MAX_QUERY_LENGTH);
293
- }
294
- let tokens = normalized.split(' ').filter(t => t.length > 0);
295
- if (tokens.length === 0) {
296
- return '';
297
- }
298
- if (tokens.length > MAX_TOKENS) {
299
- logger.warn(`[KG] FTS5 query has too many tokens (${tokens.length}), using first ${MAX_TOKENS}`);
300
- tokens = tokens.slice(0, MAX_TOKENS);
301
- }
302
- const ftsTokens = tokens
303
- .filter(token => {
304
- const upper = token.toUpperCase();
305
- return upper !== 'AND' && upper !== 'OR' && upper !== 'NOT' && upper !== 'NEAR';
306
- })
307
- .map(token => {
308
- const escaped = token
309
- .replace(/"/g, '""')
310
- .replace(/\*/g, '')
311
- .replace(/\^/g, '')
312
- .replace(/:/g, '')
313
- .replace(/[(){}[\]]/g, '');
314
- if (!escaped) {
315
- return null;
316
- }
317
- return `"${escaped}"*`;
318
- })
319
- .filter((t) => t !== null);
320
- if (ftsTokens.length === 0) {
321
- return '';
322
- }
323
- return ftsTokens.join(' OR ');
270
+ return this.searchEngine.prepareFTS5Query(query);
324
271
  }
325
- createEntity(entity) {
272
+ createEntity(entity, skipEmbedding = false) {
326
273
  this.validateEntityName(entity.name);
327
274
  try {
328
275
  if (entity.contentHash) {
@@ -385,7 +332,7 @@ export class KnowledgeGraph {
385
332
  return entity.name;
386
333
  })();
387
334
  this.queryCache.invalidatePattern(/^entities:/);
388
- if (this.vectorEnabled) {
335
+ if (this.vectorEnabled && !skipEmbedding) {
389
336
  this.generateEmbeddingAsync(entity.name, entity.observations);
390
337
  }
391
338
  logger.info(`[KG] Created entity: ${entity.name} (type: ${entity.entityType})`);
@@ -406,6 +353,41 @@ export class KnowledgeGraph {
406
353
  throw error;
407
354
  }
408
355
  }
356
+ createEntitiesBatch(entities) {
357
+ const results = [];
358
+ if (entities.length === 0) {
359
+ return results;
360
+ }
361
+ const transaction = this.db.transaction(() => {
362
+ for (const entity of entities) {
363
+ try {
364
+ this.createEntity({
365
+ name: entity.name,
366
+ entityType: entity.entityType,
367
+ observations: entity.observations,
368
+ tags: entity.tags,
369
+ metadata: entity.metadata,
370
+ contentHash: entity.contentHash,
371
+ }, true);
372
+ results.push({ name: entity.name, success: true });
373
+ }
374
+ catch (error) {
375
+ results.push({
376
+ name: entity.name,
377
+ success: false,
378
+ error: error instanceof Error ? error.message : String(error),
379
+ });
380
+ }
381
+ }
382
+ });
383
+ transaction();
384
+ this.queryCache.invalidatePattern(/^entities:/);
385
+ this.queryCache.invalidatePattern(/^stats:/);
386
+ if (this.vectorEnabled) {
387
+ this.generateBatchEmbeddingsAsync(entities, results);
388
+ }
389
+ return results;
390
+ }
409
391
  createRelation(relation) {
410
392
  this.validateEntityName(relation.from);
411
393
  this.validateEntityName(relation.to);
@@ -431,106 +413,7 @@ export class KnowledgeGraph {
431
413
  logger.info(`[KG] Created relation: ${relation.from} -[${relation.relationType}]-> ${relation.to}`);
432
414
  }
433
415
  searchEntities(query) {
434
- const MAX_LIMIT = 1000;
435
- if (query.limit === 0) {
436
- return [];
437
- }
438
- let effectiveLimit = query.limit;
439
- if (query.limit !== undefined) {
440
- if (query.limit < 0) {
441
- throw new ValidationError('Limit must be non-negative', {
442
- component: 'KnowledgeGraph',
443
- method: 'searchEntities',
444
- providedLimit: query.limit,
445
- });
446
- }
447
- if (query.limit > MAX_LIMIT) {
448
- logger.warn(`Limit ${query.limit} exceeds maximum, capping to ${MAX_LIMIT}`);
449
- effectiveLimit = MAX_LIMIT;
450
- }
451
- }
452
- if (query.offset !== undefined && query.offset < 0) {
453
- throw new ValidationError('Offset must be non-negative', {
454
- component: 'KnowledgeGraph',
455
- method: 'searchEntities',
456
- providedOffset: query.offset,
457
- });
458
- }
459
- if (query.namePattern !== undefined && query.namePattern !== '') {
460
- validateNonEmptyString(query.namePattern, 'Name pattern');
461
- if (CONTROL_CHAR_PATTERN.test(query.namePattern)) {
462
- throw new ValidationError('Name pattern must not contain control characters', {
463
- component: 'KnowledgeGraph',
464
- method: 'searchEntities',
465
- namePattern: query.namePattern.slice(0, 100),
466
- });
467
- }
468
- }
469
- const cacheKeyQuery = { ...query, limit: effectiveLimit };
470
- const cacheKey = `entities:${JSON.stringify(cacheKeyQuery)}`;
471
- const cached = this.queryCache.get(cacheKey);
472
- if (cached) {
473
- return cached;
474
- }
475
- let sql = `
476
- SELECT e.*,
477
- (SELECT json_group_array(content) FROM observations o WHERE o.entity_id = e.id) as observations_json,
478
- (SELECT json_group_array(tag) FROM tags t WHERE t.entity_id = e.id) as tags_json
479
- FROM entities e
480
- WHERE 1=1
481
- `;
482
- const params = [];
483
- if (query.entityType) {
484
- sql += ' AND e.type = ?';
485
- params.push(query.entityType);
486
- }
487
- if (query.tag) {
488
- sql += ' AND e.id IN (SELECT entity_id FROM tags WHERE tag = ?)';
489
- params.push(query.tag);
490
- }
491
- if (query.namePattern) {
492
- const ftsResults = this.searchFTS5(query.namePattern, effectiveLimit || 100);
493
- if (ftsResults.length > 0) {
494
- sql += ' AND e.id IN (' + ftsResults.map(() => '?').join(',') + ')';
495
- params.push(...ftsResults);
496
- }
497
- else {
498
- sql += " AND (e.name LIKE ? ESCAPE '!' OR e.id IN (SELECT entity_id FROM observations WHERE content LIKE ? ESCAPE '!'))";
499
- const escapedPattern = `%${this.escapeLikePattern(query.namePattern)}%`;
500
- params.push(escapedPattern);
501
- params.push(escapedPattern);
502
- }
503
- }
504
- sql += ' ORDER BY e.created_at DESC';
505
- if (effectiveLimit !== undefined) {
506
- sql += ' LIMIT ?';
507
- params.push(effectiveLimit);
508
- }
509
- if (query.offset !== undefined) {
510
- sql += ' OFFSET ?';
511
- params.push(query.offset);
512
- }
513
- const stmt = this.db.prepare(sql);
514
- const rows = stmt.all(...params);
515
- const entities = new Array(rows.length);
516
- for (let i = 0; i < rows.length; i++) {
517
- const r = rows[i];
518
- const observations = safeJsonParse(r.observations_json, [])
519
- .filter(value => value);
520
- const tags = safeJsonParse(r.tags_json, [])
521
- .filter(value => value);
522
- entities[i] = {
523
- id: r.id,
524
- name: r.name,
525
- entityType: r.type,
526
- observations,
527
- tags,
528
- metadata: r.metadata ? safeJsonParse(r.metadata, {}) : {},
529
- createdAt: new Date(r.created_at)
530
- };
531
- }
532
- this.queryCache.set(cacheKey, entities);
533
- return entities;
416
+ return this.searchEngine.searchEntities(query);
534
417
  }
535
418
  getEntity(name) {
536
419
  this.validateEntityName(name);
@@ -636,9 +519,9 @@ export class KnowledgeGraph {
636
519
  VALUES('delete', ?, ?, ?)
637
520
  `).run(entity.id, existingFts.name, existingFts.observations);
638
521
  }
639
- if (this.vectorEnabled && this.vectorExt) {
522
+ if (this.vectorEnabled && this.vectorAdapter) {
640
523
  try {
641
- this.vectorExt.deleteEmbedding(this.db, name);
524
+ this.vectorAdapter.deleteEmbedding(this.db, name);
642
525
  }
643
526
  catch (error) {
644
527
  logger.warn('[KG] Failed to delete embedding during entity removal', {
@@ -647,6 +530,11 @@ export class KnowledgeGraph {
647
530
  });
648
531
  }
649
532
  }
533
+ try {
534
+ this.db.prepare('DELETE FROM embedding_hashes WHERE entity_name = ?').run(name);
535
+ }
536
+ catch {
537
+ }
650
538
  const stmt = this.db.prepare('DELETE FROM entities WHERE name = ?');
651
539
  return stmt.run(name);
652
540
  })();
@@ -658,20 +546,33 @@ export class KnowledgeGraph {
658
546
  return result.changes > 0;
659
547
  }
660
548
  generateEmbeddingAsync(entityName, observations) {
661
- if (!this.vectorExt)
549
+ if (!this.vectorAdapter)
662
550
  return;
663
551
  const text = [entityName, ...(observations || [])].join(' ');
664
- const ext = this.vectorExt;
552
+ const adapter = this.vectorAdapter;
553
+ const newHash = ContentHasher.hashEmbeddingSource(entityName, observations || []);
554
+ try {
555
+ const existing = this.db
556
+ .prepare('SELECT hash FROM embedding_hashes WHERE entity_name = ?')
557
+ .get(entityName);
558
+ if (existing && existing.hash === newHash) {
559
+ logger.debug(`[KG] Embedding hash unchanged, skipping: ${entityName}`);
560
+ return;
561
+ }
562
+ }
563
+ catch {
564
+ }
665
565
  const task = (async () => {
666
566
  try {
667
567
  const { LazyEmbeddingService } = await import('../embeddings/EmbeddingService.js');
668
568
  const service = await LazyEmbeddingService.get();
669
569
  const embedding = await service.encode(text);
670
- ext.insertEmbedding(this.db, entityName, embedding);
570
+ adapter.insertEmbedding(this.db, entityName, embedding);
571
+ this.db.prepare('INSERT OR REPLACE INTO embedding_hashes (entity_name, hash) VALUES (?, ?)').run(entityName, newHash);
671
572
  logger.debug(`[KG] Embedding generated for: ${entityName}`);
672
573
  }
673
574
  catch (error) {
674
- logger.debug('[KG] Embedding generation skipped', {
575
+ logger.warn('[KG] Embedding generation failed', {
675
576
  entity: entityName,
676
577
  reason: error instanceof Error ? error.message : String(error),
677
578
  });
@@ -680,65 +581,69 @@ export class KnowledgeGraph {
680
581
  this.pendingEmbeddings.add(task);
681
582
  task.finally(() => this.pendingEmbeddings.delete(task));
682
583
  }
683
- async semanticSearch(query, options = {}) {
684
- const { limit = 10, minSimilarity = 0.3 } = options;
685
- if (this.vectorInitPromise) {
686
- await this.vectorInitPromise;
687
- }
688
- if (!this.vectorEnabled || !this.vectorExt) {
689
- return this.keywordSearchAsSemanticResults(query, limit);
690
- }
691
- try {
692
- const { LazyEmbeddingService } = await import('../embeddings/EmbeddingService.js');
693
- const service = await LazyEmbeddingService.get();
694
- const queryEmbedding = await service.encode(query);
695
- const knnResults = this.vectorExt.knnSearch(this.db, queryEmbedding, limit * 2);
696
- const results = [];
697
- for (const knn of knnResults) {
698
- const similarity = 1 - knn.distance;
699
- if (similarity < minSimilarity)
700
- continue;
701
- const entity = this.getEntity(knn.entityName);
702
- if (!entity)
584
+ generateBatchEmbeddingsAsync(entities, results) {
585
+ if (!this.vectorAdapter)
586
+ return;
587
+ const adapter = this.vectorAdapter;
588
+ const toEmbed = [];
589
+ for (let i = 0; i < entities.length; i++) {
590
+ if (!results[i]?.success)
591
+ continue;
592
+ const entity = entities[i];
593
+ const newHash = ContentHasher.hashEmbeddingSource(entity.name, entity.observations);
594
+ try {
595
+ const existing = this.db
596
+ .prepare('SELECT hash FROM embedding_hashes WHERE entity_name = ?')
597
+ .get(entity.name);
598
+ if (existing && existing.hash === newHash) {
599
+ logger.debug(`[KG] Batch: embedding hash unchanged, skipping: ${entity.name}`);
703
600
  continue;
704
- results.push({ entity, similarity });
601
+ }
705
602
  }
706
- return results.slice(0, limit);
707
- }
708
- catch (error) {
709
- logger.warn('[KG] Semantic search failed, falling back to keyword', {
710
- error: error instanceof Error ? error.message : String(error),
603
+ catch {
604
+ }
605
+ toEmbed.push({
606
+ name: entity.name,
607
+ text: [entity.name, ...entity.observations].join(' '),
608
+ hash: newHash,
711
609
  });
712
- return this.keywordSearchAsSemanticResults(query, limit);
713
- }
714
- }
715
- async hybridSearch(query, options = {}) {
716
- const { limit = 10, minSimilarity = 0.3 } = options;
717
- const keywordResults = this.keywordSearchAsSemanticResults(query, limit);
718
- if (this.vectorInitPromise) {
719
- await this.vectorInitPromise;
720
- }
721
- if (!this.vectorEnabled) {
722
- return keywordResults;
723
- }
724
- const semanticResults = await this.semanticSearch(query, { limit, minSimilarity });
725
- const merged = new Map();
726
- for (const r of keywordResults) {
727
- merged.set(r.entity.name, r);
728
610
  }
729
- for (const r of semanticResults) {
730
- const existing = merged.get(r.entity.name);
731
- if (!existing || r.similarity > existing.similarity) {
732
- merged.set(r.entity.name, r);
611
+ if (toEmbed.length === 0)
612
+ return;
613
+ const task = (async () => {
614
+ try {
615
+ const { LazyEmbeddingService } = await import('../embeddings/EmbeddingService.js');
616
+ const service = await LazyEmbeddingService.get();
617
+ const embeddings = await service.encodeBatch(toEmbed.map(e => e.text));
618
+ for (let i = 0; i < toEmbed.length; i++) {
619
+ try {
620
+ adapter.insertEmbedding(this.db, toEmbed[i].name, embeddings[i]);
621
+ this.db.prepare('INSERT OR REPLACE INTO embedding_hashes (entity_name, hash) VALUES (?, ?)').run(toEmbed[i].name, toEmbed[i].hash);
622
+ }
623
+ catch (error) {
624
+ logger.warn('[KG] Batch embedding insert failed', {
625
+ entity: toEmbed[i].name,
626
+ reason: error instanceof Error ? error.message : String(error),
627
+ });
628
+ }
629
+ }
630
+ logger.debug(`[KG] Batch embeddings generated for ${toEmbed.length} entities`);
733
631
  }
734
- }
735
- return Array.from(merged.values())
736
- .sort((a, b) => b.similarity - a.similarity)
737
- .slice(0, limit);
632
+ catch (error) {
633
+ logger.warn('[KG] Batch embedding generation failed', {
634
+ count: toEmbed.length,
635
+ reason: error instanceof Error ? error.message : String(error),
636
+ });
637
+ }
638
+ })();
639
+ this.pendingEmbeddings.add(task);
640
+ task.finally(() => this.pendingEmbeddings.delete(task));
738
641
  }
739
- keywordSearchAsSemanticResults(query, limit) {
740
- const entities = this.searchEntities({ namePattern: query, limit });
741
- return entities.map(entity => ({ entity, similarity: 0.5 }));
642
+ async semanticSearch(query, options = {}) {
643
+ return this.searchEngine.semanticSearch(query, options);
644
+ }
645
+ async hybridSearch(query, options = {}) {
646
+ return this.searchEngine.hybridSearch(query, options);
742
647
  }
743
648
  isVectorSearchEnabled() {
744
649
  return this.vectorEnabled;