@knowledgine/core 0.0.1 → 0.2.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 (123) hide show
  1. package/dist/config/config-loader.d.ts +15 -0
  2. package/dist/config/config-loader.d.ts.map +1 -0
  3. package/dist/config/config-loader.js +46 -0
  4. package/dist/config/config-loader.js.map +1 -0
  5. package/dist/config.d.ts +16 -0
  6. package/dist/config.d.ts.map +1 -1
  7. package/dist/config.js +17 -0
  8. package/dist/config.js.map +1 -1
  9. package/dist/embedding/embedding-provider.d.ts +9 -0
  10. package/dist/embedding/embedding-provider.d.ts.map +1 -0
  11. package/dist/embedding/embedding-provider.js +2 -0
  12. package/dist/embedding/embedding-provider.js.map +1 -0
  13. package/dist/embedding/model-downloader.d.ts +34 -0
  14. package/dist/embedding/model-downloader.d.ts.map +1 -0
  15. package/dist/embedding/model-downloader.js +149 -0
  16. package/dist/embedding/model-downloader.js.map +1 -0
  17. package/dist/embedding/model-manager.d.ts +10 -0
  18. package/dist/embedding/model-manager.d.ts.map +1 -0
  19. package/dist/embedding/model-manager.js +32 -0
  20. package/dist/embedding/model-manager.js.map +1 -0
  21. package/dist/embedding/onnx-embedding-provider.d.ts +18 -0
  22. package/dist/embedding/onnx-embedding-provider.d.ts.map +1 -0
  23. package/dist/embedding/onnx-embedding-provider.js +121 -0
  24. package/dist/embedding/onnx-embedding-provider.js.map +1 -0
  25. package/dist/embedding/tokenizer.d.ts +19 -0
  26. package/dist/embedding/tokenizer.d.ts.map +1 -0
  27. package/dist/embedding/tokenizer.js +80 -0
  28. package/dist/embedding/tokenizer.js.map +1 -0
  29. package/dist/errors.d.ts +12 -0
  30. package/dist/errors.d.ts.map +1 -1
  31. package/dist/errors.js +21 -0
  32. package/dist/errors.js.map +1 -1
  33. package/dist/feedback/feedback-learner.d.ts +29 -0
  34. package/dist/feedback/feedback-learner.d.ts.map +1 -0
  35. package/dist/feedback/feedback-learner.js +88 -0
  36. package/dist/feedback/feedback-learner.js.map +1 -0
  37. package/dist/feedback/feedback-repository.d.ts +41 -0
  38. package/dist/feedback/feedback-repository.d.ts.map +1 -0
  39. package/dist/feedback/feedback-repository.js +94 -0
  40. package/dist/feedback/feedback-repository.js.map +1 -0
  41. package/dist/feedback/index.d.ts +5 -0
  42. package/dist/feedback/index.d.ts.map +1 -0
  43. package/dist/feedback/index.js +3 -0
  44. package/dist/feedback/index.js.map +1 -0
  45. package/dist/graph/entity-extractor.d.ts +26 -0
  46. package/dist/graph/entity-extractor.d.ts.map +1 -0
  47. package/dist/graph/entity-extractor.js +237 -0
  48. package/dist/graph/entity-extractor.js.map +1 -0
  49. package/dist/graph/graph-repository.d.ts +72 -0
  50. package/dist/graph/graph-repository.d.ts.map +1 -0
  51. package/dist/graph/graph-repository.js +442 -0
  52. package/dist/graph/graph-repository.js.map +1 -0
  53. package/dist/graph/index.d.ts +4 -0
  54. package/dist/graph/index.d.ts.map +1 -0
  55. package/dist/graph/index.js +4 -0
  56. package/dist/graph/index.js.map +1 -0
  57. package/dist/graph/relation-inferrer.d.ts +23 -0
  58. package/dist/graph/relation-inferrer.d.ts.map +1 -0
  59. package/dist/graph/relation-inferrer.js +89 -0
  60. package/dist/graph/relation-inferrer.js.map +1 -0
  61. package/dist/index.d.ts +33 -5
  62. package/dist/index.d.ts.map +1 -1
  63. package/dist/index.js +37 -4
  64. package/dist/index.js.map +1 -1
  65. package/dist/provenance/provenance-repository.d.ts +47 -0
  66. package/dist/provenance/provenance-repository.d.ts.map +1 -0
  67. package/dist/provenance/provenance-repository.js +121 -0
  68. package/dist/provenance/provenance-repository.js.map +1 -0
  69. package/dist/search/hybrid-searcher.d.ts +14 -0
  70. package/dist/search/hybrid-searcher.d.ts.map +1 -0
  71. package/dist/search/hybrid-searcher.js +67 -0
  72. package/dist/search/hybrid-searcher.js.map +1 -0
  73. package/dist/search/knowledge-searcher.d.ts +8 -4
  74. package/dist/search/knowledge-searcher.d.ts.map +1 -1
  75. package/dist/search/knowledge-searcher.js +47 -16
  76. package/dist/search/knowledge-searcher.js.map +1 -1
  77. package/dist/search/link-generator.d.ts +7 -1
  78. package/dist/search/link-generator.d.ts.map +1 -1
  79. package/dist/search/link-generator.js +37 -1
  80. package/dist/search/link-generator.js.map +1 -1
  81. package/dist/search/semantic-searcher.d.ts +14 -0
  82. package/dist/search/semantic-searcher.d.ts.map +1 -0
  83. package/dist/search/semantic-searcher.js +30 -0
  84. package/dist/search/semantic-searcher.js.map +1 -0
  85. package/dist/services/knowledge-service.d.ts +128 -0
  86. package/dist/services/knowledge-service.d.ts.map +1 -0
  87. package/dist/services/knowledge-service.js +168 -0
  88. package/dist/services/knowledge-service.js.map +1 -0
  89. package/dist/storage/database.d.ts +9 -1
  90. package/dist/storage/database.d.ts.map +1 -1
  91. package/dist/storage/database.js +28 -1
  92. package/dist/storage/database.js.map +1 -1
  93. package/dist/storage/knowledge-repository.d.ts +27 -0
  94. package/dist/storage/knowledge-repository.d.ts.map +1 -1
  95. package/dist/storage/knowledge-repository.js +107 -3
  96. package/dist/storage/knowledge-repository.js.map +1 -1
  97. package/dist/storage/migrations/003_vector_embeddings.d.ts +3 -0
  98. package/dist/storage/migrations/003_vector_embeddings.d.ts.map +1 -0
  99. package/dist/storage/migrations/003_vector_embeddings.js +50 -0
  100. package/dist/storage/migrations/003_vector_embeddings.js.map +1 -0
  101. package/dist/storage/migrations/004_knowledge_graph.d.ts +3 -0
  102. package/dist/storage/migrations/004_knowledge_graph.d.ts.map +1 -0
  103. package/dist/storage/migrations/004_knowledge_graph.js +106 -0
  104. package/dist/storage/migrations/004_knowledge_graph.js.map +1 -0
  105. package/dist/storage/migrations/005a_events_layer.d.ts +3 -0
  106. package/dist/storage/migrations/005a_events_layer.d.ts.map +1 -0
  107. package/dist/storage/migrations/005a_events_layer.js +55 -0
  108. package/dist/storage/migrations/005a_events_layer.js.map +1 -0
  109. package/dist/storage/migrations/005b_bitemporal.d.ts +3 -0
  110. package/dist/storage/migrations/005b_bitemporal.d.ts.map +1 -0
  111. package/dist/storage/migrations/005b_bitemporal.js +53 -0
  112. package/dist/storage/migrations/005b_bitemporal.js.map +1 -0
  113. package/dist/storage/migrations/005c_provenance.d.ts +3 -0
  114. package/dist/storage/migrations/005c_provenance.d.ts.map +1 -0
  115. package/dist/storage/migrations/005c_provenance.js +56 -0
  116. package/dist/storage/migrations/005c_provenance.js.map +1 -0
  117. package/dist/storage/migrations/006_extraction_feedback.d.ts +3 -0
  118. package/dist/storage/migrations/006_extraction_feedback.d.ts.map +1 -0
  119. package/dist/storage/migrations/006_extraction_feedback.js +30 -0
  120. package/dist/storage/migrations/006_extraction_feedback.js.map +1 -0
  121. package/dist/types.d.ts +40 -0
  122. package/dist/types.d.ts.map +1 -1
  123. package/package.json +15 -4
@@ -0,0 +1,442 @@
1
+ import { DatabaseError, ValidationError } from "../errors.js";
2
+ function rowToEntity(row) {
3
+ return {
4
+ id: row.id,
5
+ name: row.name,
6
+ entityType: row.entity_type,
7
+ description: row.description ?? undefined,
8
+ createdAt: row.created_at,
9
+ updatedAt: row.updated_at ?? undefined,
10
+ metadata: row.metadata_json
11
+ ? JSON.parse(row.metadata_json)
12
+ : undefined,
13
+ };
14
+ }
15
+ function rowToRelation(row) {
16
+ return {
17
+ id: row.id,
18
+ fromEntityId: row.from_entity_id,
19
+ toEntityId: row.to_entity_id,
20
+ relationType: row.relation_type,
21
+ strength: row.strength,
22
+ description: row.description ?? undefined,
23
+ createdAt: row.created_at,
24
+ };
25
+ }
26
+ function rowToObservation(row) {
27
+ return {
28
+ id: row.id,
29
+ entityId: row.entity_id,
30
+ content: row.content,
31
+ observationType: row.observation_type,
32
+ confidence: row.confidence ?? undefined,
33
+ sourceNoteId: row.source_note_id ?? undefined,
34
+ sourcePatternId: row.source_pattern_id ?? undefined,
35
+ createdAt: row.created_at,
36
+ metadata: row.metadata_json
37
+ ? JSON.parse(row.metadata_json)
38
+ : undefined,
39
+ };
40
+ }
41
+ export class GraphRepository {
42
+ db;
43
+ constructor(db) {
44
+ this.db = db;
45
+ }
46
+ // ── Entity CRUD ──────────────────────────────────────────────
47
+ createEntity(entity) {
48
+ if (!entity.name || entity.name.trim() === "") {
49
+ throw new ValidationError("name", entity.name, "Entity name is required");
50
+ }
51
+ try {
52
+ const now = new Date().toISOString();
53
+ const stmt = this.db.prepare(`
54
+ INSERT INTO entities (name, entity_type, description, created_at, updated_at, metadata_json)
55
+ VALUES (?, ?, ?, ?, ?, ?)
56
+ `);
57
+ const info = stmt.run(entity.name.toLowerCase(), entity.entityType, entity.description ?? null, entity.createdAt || now, entity.updatedAt ?? null, entity.metadata ? JSON.stringify(entity.metadata) : null);
58
+ return Number(info.lastInsertRowid);
59
+ }
60
+ catch (error) {
61
+ if (error instanceof ValidationError)
62
+ throw error;
63
+ throw new DatabaseError("createEntity", error, { name: entity.name });
64
+ }
65
+ }
66
+ /**
67
+ * 名前を小文字正規化してupsert。同名・同タイプのエンティティは更新する。
68
+ */
69
+ upsertEntity(entity) {
70
+ if (!entity.name || entity.name.trim() === "") {
71
+ throw new ValidationError("name", entity.name, "Entity name is required");
72
+ }
73
+ try {
74
+ const normalizedName = entity.name.toLowerCase();
75
+ const now = new Date().toISOString();
76
+ const stmt = this.db.prepare(`
77
+ INSERT INTO entities (name, entity_type, description, created_at, updated_at, metadata_json)
78
+ VALUES (?, ?, ?, ?, ?, ?)
79
+ ON CONFLICT(name, entity_type) DO UPDATE SET
80
+ description = COALESCE(excluded.description, description),
81
+ updated_at = excluded.updated_at,
82
+ metadata_json = COALESCE(excluded.metadata_json, metadata_json)
83
+ `);
84
+ stmt.run(normalizedName, entity.entityType, entity.description ?? null, entity.createdAt || now, now, entity.metadata ? JSON.stringify(entity.metadata) : null);
85
+ const existing = this.getEntityByName(normalizedName, entity.entityType);
86
+ return existing.id;
87
+ }
88
+ catch (error) {
89
+ if (error instanceof ValidationError)
90
+ throw error;
91
+ throw new DatabaseError("upsertEntity", error, { name: entity.name });
92
+ }
93
+ }
94
+ getEntityById(id) {
95
+ const row = this.db.prepare("SELECT * FROM entities WHERE id = ?").get(id);
96
+ return row ? rowToEntity(row) : undefined;
97
+ }
98
+ getEntityByName(name, entityType) {
99
+ const normalizedName = name.toLowerCase();
100
+ if (entityType) {
101
+ const row = this.db
102
+ .prepare("SELECT * FROM entities WHERE name = ? AND entity_type = ?")
103
+ .get(normalizedName, entityType);
104
+ return row ? rowToEntity(row) : undefined;
105
+ }
106
+ const row = this.db
107
+ .prepare("SELECT * FROM entities WHERE name = ? LIMIT 1")
108
+ .get(normalizedName);
109
+ return row ? rowToEntity(row) : undefined;
110
+ }
111
+ /**
112
+ * FTS5 trigram検索。3文字未満はLIKEフォールバック。
113
+ */
114
+ searchEntities(query, limit = 20) {
115
+ if (query.length < 3) {
116
+ // LIKE fallback for short queries
117
+ const rows = this.db
118
+ .prepare(`SELECT * FROM entities WHERE name LIKE ? OR description LIKE ? LIMIT ?`)
119
+ .all(`%${query}%`, `%${query}%`, limit);
120
+ return rows.map(rowToEntity);
121
+ }
122
+ try {
123
+ const rows = this.db
124
+ .prepare(`
125
+ SELECT e.* FROM entities e
126
+ JOIN entities_fts fts ON e.id = fts.rowid
127
+ WHERE entities_fts MATCH ?
128
+ ORDER BY rank
129
+ LIMIT ?
130
+ `)
131
+ .all(query, limit);
132
+ return rows.map(rowToEntity);
133
+ }
134
+ catch {
135
+ // FTS失敗時はLIKEフォールバック
136
+ const rows = this.db
137
+ .prepare(`SELECT * FROM entities WHERE name LIKE ? OR description LIKE ? LIMIT ?`)
138
+ .all(`%${query}%`, `%${query}%`, limit);
139
+ return rows.map(rowToEntity);
140
+ }
141
+ }
142
+ deleteEntity(id) {
143
+ try {
144
+ const info = this.db.prepare("DELETE FROM entities WHERE id = ?").run(id);
145
+ return info.changes > 0;
146
+ }
147
+ catch (error) {
148
+ throw new DatabaseError("deleteEntity", error, { id });
149
+ }
150
+ }
151
+ // ── Relation CRUD ─────────────────────────────────────────────
152
+ createRelation(relation) {
153
+ try {
154
+ const now = new Date().toISOString();
155
+ const stmt = this.db.prepare(`
156
+ INSERT INTO relations (from_entity_id, to_entity_id, relation_type, strength, description, created_at, valid_from, recorded_at)
157
+ VALUES (?, ?, ?, ?, ?, ?, datetime('now'), datetime('now'))
158
+ `);
159
+ const info = stmt.run(relation.fromEntityId, relation.toEntityId, relation.relationType, relation.strength ?? 1.0, relation.description ?? null, relation.createdAt || now);
160
+ return Number(info.lastInsertRowid);
161
+ }
162
+ catch (error) {
163
+ throw new DatabaseError("createRelation", error, {
164
+ fromEntityId: relation.fromEntityId,
165
+ toEntityId: relation.toEntityId,
166
+ });
167
+ }
168
+ }
169
+ /**
170
+ * 同一 (from, to, type) のrelationが存在する場合はstrengthをMAXで更新。
171
+ */
172
+ upsertRelation(relation) {
173
+ try {
174
+ const now = new Date().toISOString();
175
+ const strength = relation.strength ?? 1.0;
176
+ const insertStmt = this.db.prepare(`
177
+ INSERT OR IGNORE INTO relations
178
+ (from_entity_id, to_entity_id, relation_type, strength, description, created_at, valid_from, recorded_at)
179
+ VALUES (?, ?, ?, ?, ?, ?, datetime('now'), datetime('now'))
180
+ `);
181
+ insertStmt.run(relation.fromEntityId, relation.toEntityId, relation.relationType, strength, relation.description ?? null, relation.createdAt || now);
182
+ const updateStmt = this.db.prepare(`
183
+ UPDATE relations
184
+ SET strength = MAX(strength, ?)
185
+ WHERE from_entity_id = ? AND to_entity_id = ? AND relation_type = ?
186
+ `);
187
+ updateStmt.run(strength, relation.fromEntityId, relation.toEntityId, relation.relationType);
188
+ const existing = this.db
189
+ .prepare("SELECT id FROM relations WHERE from_entity_id = ? AND to_entity_id = ? AND relation_type = ?")
190
+ .get(relation.fromEntityId, relation.toEntityId, relation.relationType);
191
+ return existing?.id ?? 0;
192
+ }
193
+ catch (error) {
194
+ throw new DatabaseError("upsertRelation", error, {
195
+ fromEntityId: relation.fromEntityId,
196
+ toEntityId: relation.toEntityId,
197
+ });
198
+ }
199
+ }
200
+ getRelationsByEntityId(entityId) {
201
+ const rows = this.db
202
+ .prepare("SELECT * FROM active_relations WHERE from_entity_id = ? OR to_entity_id = ? ORDER BY strength DESC")
203
+ .all(entityId, entityId);
204
+ return rows.map(rowToRelation);
205
+ }
206
+ deleteRelation(id) {
207
+ try {
208
+ const info = this.db.prepare("DELETE FROM relations WHERE id = ?").run(id);
209
+ return info.changes > 0;
210
+ }
211
+ catch (error) {
212
+ throw new DatabaseError("deleteRelation", error, { id });
213
+ }
214
+ }
215
+ // ── Observation CRUD ──────────────────────────────────────────
216
+ createObservation(observation) {
217
+ try {
218
+ const now = new Date().toISOString();
219
+ const stmt = this.db.prepare(`
220
+ INSERT INTO observations
221
+ (entity_id, content, observation_type, confidence, source_note_id, source_pattern_id, created_at, metadata_json, valid_from, recorded_at)
222
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, datetime('now'), datetime('now'))
223
+ `);
224
+ const info = stmt.run(observation.entityId, observation.content, observation.observationType, observation.confidence ?? null, observation.sourceNoteId ?? null, observation.sourcePatternId ?? null, observation.createdAt || now, observation.metadata ? JSON.stringify(observation.metadata) : null);
225
+ return Number(info.lastInsertRowid);
226
+ }
227
+ catch (error) {
228
+ throw new DatabaseError("createObservation", error, { entityId: observation.entityId });
229
+ }
230
+ }
231
+ getObservationsByEntityId(entityId) {
232
+ const rows = this.db
233
+ .prepare("SELECT * FROM active_observations WHERE entity_id = ? ORDER BY created_at DESC")
234
+ .all(entityId);
235
+ return rows.map(rowToObservation);
236
+ }
237
+ deleteObservation(id) {
238
+ try {
239
+ const info = this.db.prepare("DELETE FROM observations WHERE id = ?").run(id);
240
+ return info.changes > 0;
241
+ }
242
+ catch (error) {
243
+ throw new DatabaseError("deleteObservation", error, { id });
244
+ }
245
+ }
246
+ // ── Entity-Note Links ─────────────────────────────────────────
247
+ linkEntityToNote(entityId, noteId) {
248
+ try {
249
+ this.db
250
+ .prepare("INSERT OR IGNORE INTO entity_note_links (entity_id, note_id) VALUES (?, ?)")
251
+ .run(entityId, noteId);
252
+ }
253
+ catch (error) {
254
+ throw new DatabaseError("linkEntityToNote", error, { entityId, noteId });
255
+ }
256
+ }
257
+ getLinkedNotes(entityId) {
258
+ const rows = this.db
259
+ .prepare("SELECT entity_id, note_id FROM entity_note_links WHERE entity_id = ?")
260
+ .all(entityId);
261
+ return rows.map((r) => ({ entityId: r.entity_id, noteId: r.note_id }));
262
+ }
263
+ getLinkedEntities(noteId) {
264
+ const rows = this.db
265
+ .prepare(`
266
+ SELECT e.* FROM entities e
267
+ JOIN entity_note_links l ON e.id = l.entity_id
268
+ WHERE l.note_id = ?
269
+ `)
270
+ .all(noteId);
271
+ return rows.map(rowToEntity);
272
+ }
273
+ // ── Graph Traversal ───────────────────────────────────────────
274
+ getEntityWithGraph(entityId) {
275
+ const entity = this.getEntityById(entityId);
276
+ if (!entity)
277
+ return undefined;
278
+ const observations = this.getObservationsByEntityId(entityId);
279
+ const outgoingRows = this.db
280
+ .prepare(`
281
+ SELECT r.*, e.id as te_id, e.name as te_name, e.entity_type as te_type,
282
+ e.description as te_desc, e.created_at as te_created, e.updated_at as te_updated, e.metadata_json as te_meta
283
+ FROM active_relations r
284
+ JOIN entities e ON e.id = r.to_entity_id
285
+ WHERE r.from_entity_id = ?
286
+ ORDER BY r.strength DESC
287
+ `)
288
+ .all(entityId);
289
+ const outgoingRelations = outgoingRows.map((row) => ({
290
+ ...rowToRelation(row),
291
+ targetEntity: rowToEntity({
292
+ id: row.te_id,
293
+ name: row.te_name,
294
+ entity_type: row.te_type,
295
+ description: row.te_desc,
296
+ created_at: row.te_created,
297
+ updated_at: row.te_updated,
298
+ metadata_json: row.te_meta,
299
+ }),
300
+ }));
301
+ const incomingRows = this.db
302
+ .prepare(`
303
+ SELECT r.*, e.id as se_id, e.name as se_name, e.entity_type as se_type,
304
+ e.description as se_desc, e.created_at as se_created, e.updated_at as se_updated, e.metadata_json as se_meta
305
+ FROM active_relations r
306
+ JOIN entities e ON e.id = r.from_entity_id
307
+ WHERE r.to_entity_id = ?
308
+ ORDER BY r.strength DESC
309
+ `)
310
+ .all(entityId);
311
+ const incomingRelations = incomingRows.map((row) => ({
312
+ ...rowToRelation(row),
313
+ sourceEntity: rowToEntity({
314
+ id: row.se_id,
315
+ name: row.se_name,
316
+ entity_type: row.se_type,
317
+ description: row.se_desc,
318
+ created_at: row.se_created,
319
+ updated_at: row.se_updated,
320
+ metadata_json: row.se_meta,
321
+ }),
322
+ }));
323
+ const linkedNoteRows = this.db
324
+ .prepare(`
325
+ SELECT l.entity_id, l.note_id, n.file_path, n.title, n.created_at
326
+ FROM entity_note_links l
327
+ JOIN knowledge_notes n ON n.id = l.note_id
328
+ WHERE l.entity_id = ?
329
+ `)
330
+ .all(entityId);
331
+ const linkedNotes = linkedNoteRows.map((row) => ({
332
+ entityId: row.entity_id,
333
+ noteId: row.note_id,
334
+ note: {
335
+ filePath: row.file_path,
336
+ title: row.title,
337
+ createdAt: row.created_at,
338
+ },
339
+ }));
340
+ return {
341
+ ...entity,
342
+ observations,
343
+ outgoingRelations,
344
+ incomingRelations,
345
+ linkedNotes,
346
+ };
347
+ }
348
+ /**
349
+ * 幅優先探索でhops内の関連エンティティを取得。
350
+ * 循環グラフ対策: visitedセットで重複訪問を防ぐ。maxHops上限は3。
351
+ */
352
+ findRelatedEntities(entityId, maxHops = 1) {
353
+ const safeMaxHops = Math.min(maxHops, 3);
354
+ const visited = new Set([entityId]);
355
+ const result = [];
356
+ let frontier = [entityId];
357
+ for (let hop = 1; hop <= safeMaxHops; hop++) {
358
+ if (frontier.length === 0)
359
+ break;
360
+ const placeholders = frontier.map(() => "?").join(",");
361
+ const nextIds = [];
362
+ const rows = this.db
363
+ .prepare(`
364
+ SELECT DISTINCT
365
+ CASE WHEN r.from_entity_id IN (${placeholders}) THEN r.to_entity_id
366
+ ELSE r.from_entity_id END as neighbor_id
367
+ FROM active_relations r
368
+ WHERE r.from_entity_id IN (${placeholders}) OR r.to_entity_id IN (${placeholders})
369
+ `)
370
+ .all(...frontier, ...frontier, ...frontier);
371
+ for (const { neighbor_id } of rows) {
372
+ if (visited.has(neighbor_id))
373
+ continue;
374
+ visited.add(neighbor_id);
375
+ nextIds.push(neighbor_id);
376
+ const entity = this.getEntityById(neighbor_id);
377
+ if (entity) {
378
+ result.push({ ...entity, hops: hop });
379
+ }
380
+ }
381
+ frontier = nextIds;
382
+ }
383
+ return result;
384
+ }
385
+ // ── Stats ─────────────────────────────────────────────────────
386
+ getGraphStats() {
387
+ const totalEntities = this.db.prepare("SELECT COUNT(*) as count FROM entities").get().count;
388
+ const totalRelations = this.db.prepare("SELECT COUNT(*) as count FROM active_relations").get().count;
389
+ const totalObservations = this.db.prepare("SELECT COUNT(*) as count FROM active_observations").get().count;
390
+ const entityTypeRows = this.db
391
+ .prepare("SELECT entity_type, COUNT(*) as count FROM entities GROUP BY entity_type")
392
+ .all();
393
+ const entitiesByType = {};
394
+ for (const row of entityTypeRows) {
395
+ entitiesByType[row.entity_type] = row.count;
396
+ }
397
+ const relationTypeRows = this.db
398
+ .prepare("SELECT relation_type, COUNT(*) as count FROM active_relations GROUP BY relation_type")
399
+ .all();
400
+ const relationsByType = {};
401
+ for (const row of relationTypeRows) {
402
+ relationsByType[row.relation_type] = row.count;
403
+ }
404
+ return { totalEntities, totalRelations, totalObservations, entitiesByType, relationsByType };
405
+ }
406
+ // ── Bi-temporal Operations ────────────────────────────────────
407
+ invalidateRelation(id, validTo) {
408
+ try {
409
+ const info = this.db
410
+ .prepare(`UPDATE relations SET valid_to = COALESCE(?, datetime('now')) WHERE id = ? AND valid_to IS NULL`)
411
+ .run(validTo ?? null, id);
412
+ return info.changes > 0;
413
+ }
414
+ catch (error) {
415
+ throw new DatabaseError("invalidateRelation", error, { id });
416
+ }
417
+ }
418
+ invalidateObservation(id, validTo) {
419
+ try {
420
+ const info = this.db
421
+ .prepare(`UPDATE observations SET valid_to = COALESCE(?, datetime('now')) WHERE id = ? AND valid_to IS NULL`)
422
+ .run(validTo ?? null, id);
423
+ return info.changes > 0;
424
+ }
425
+ catch (error) {
426
+ throw new DatabaseError("invalidateObservation", error, { id });
427
+ }
428
+ }
429
+ getRelationHistory(fromEntityId, toEntityId) {
430
+ const rows = this.db
431
+ .prepare(`SELECT * FROM relations WHERE from_entity_id = ? AND to_entity_id = ? ORDER BY recorded_at DESC`)
432
+ .all(fromEntityId, toEntityId);
433
+ return rows.map((row) => ({
434
+ ...rowToRelation(row),
435
+ validFrom: row.valid_from,
436
+ validTo: row.valid_to,
437
+ recordedAt: row.recorded_at,
438
+ supersededAt: row.superseded_at,
439
+ }));
440
+ }
441
+ }
442
+ //# sourceMappingURL=graph-repository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph-repository.js","sourceRoot":"","sources":["../../src/graph/graph-repository.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { GraphRepository } from "./graph-repository.js";
2
+ export { EntityExtractor } from "./entity-extractor.js";
3
+ export { RelationInferrer } from "./relation-inferrer.js";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/graph/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { GraphRepository } from "./graph-repository.js";
2
+ export { EntityExtractor } from "./entity-extractor.js";
3
+ export { RelationInferrer } from "./relation-inferrer.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/graph/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { RelationType, EntityType } from "../types.js";
2
+ export interface InferredRelation {
3
+ fromName: string;
4
+ fromType: EntityType;
5
+ toName: string;
6
+ toType: EntityType;
7
+ relationType: RelationType;
8
+ strength: number;
9
+ }
10
+ export declare class RelationInferrer {
11
+ /**
12
+ * 同一ノート内のエンティティ群から関係を推論する。
13
+ *
14
+ * @param entities - ノートから抽出されたエンティティ(name + entityType)
15
+ * @param frontmatter - フロントマターデータ
16
+ */
17
+ infer(entities: Array<{
18
+ name: string;
19
+ entityType: EntityType;
20
+ }>, frontmatter?: Record<string, unknown>): InferredRelation[];
21
+ private deduplicate;
22
+ }
23
+ //# sourceMappingURL=relation-inferrer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relation-inferrer.d.ts","sourceRoot":"","sources":["../../src/graph/relation-inferrer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE5D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,UAAU,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,UAAU,CAAC;IACnB,YAAY,EAAE,YAAY,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,gBAAgB;IAC3B;;;;;OAKG;IACH,KAAK,CACH,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,UAAU,CAAA;KAAE,CAAC,EACzD,WAAW,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GACxC,gBAAgB,EAAE;IAgFrB,OAAO,CAAC,WAAW;CAWpB"}
@@ -0,0 +1,89 @@
1
+ export class RelationInferrer {
2
+ /**
3
+ * 同一ノート内のエンティティ群から関係を推論する。
4
+ *
5
+ * @param entities - ノートから抽出されたエンティティ(name + entityType)
6
+ * @param frontmatter - フロントマターデータ
7
+ */
8
+ infer(entities, frontmatter = {}) {
9
+ const results = [];
10
+ const persons = entities.filter((e) => e.entityType === "person");
11
+ const projects = entities.filter((e) => e.entityType === "project");
12
+ const technologies = entities.filter((e) => e.entityType === "technology" || e.entityType === "tool");
13
+ // author → project: created_by
14
+ const author = frontmatter["author"];
15
+ const projectName = frontmatter["project"];
16
+ if (typeof author === "string" &&
17
+ author.trim() &&
18
+ typeof projectName === "string" &&
19
+ projectName.trim()) {
20
+ results.push({
21
+ fromName: author.trim().toLowerCase(),
22
+ fromType: "person",
23
+ toName: projectName.trim().toLowerCase(),
24
+ toType: "project",
25
+ relationType: "created_by",
26
+ strength: 0.9,
27
+ });
28
+ }
29
+ // person → project: works_on (from frontmatter project field)
30
+ if (typeof projectName === "string" && projectName.trim()) {
31
+ for (const person of persons) {
32
+ if (person.name !== author?.toString().toLowerCase()) {
33
+ results.push({
34
+ fromName: person.name,
35
+ fromType: "person",
36
+ toName: projectName.trim().toLowerCase(),
37
+ toType: "project",
38
+ relationType: "works_on",
39
+ strength: 0.7,
40
+ });
41
+ }
42
+ }
43
+ }
44
+ // import → depends_on: technology depends on other technology
45
+ // (This is simplified: if note has multiple imports, they co-occur in same context)
46
+ // technology → project: uses (project uses technology when co-occurring)
47
+ for (const project of projects) {
48
+ for (const tech of technologies) {
49
+ results.push({
50
+ fromName: project.name,
51
+ fromType: "project",
52
+ toName: tech.name,
53
+ toType: tech.entityType,
54
+ relationType: "uses",
55
+ strength: 0.5,
56
+ });
57
+ }
58
+ }
59
+ // technology depends_on: inferred from import patterns (same note)
60
+ // Only if there are multiple technologies
61
+ if (technologies.length >= 2) {
62
+ for (let i = 0; i < technologies.length; i++) {
63
+ for (let j = i + 1; j < technologies.length; j++) {
64
+ results.push({
65
+ fromName: technologies[i].name,
66
+ fromType: technologies[i].entityType,
67
+ toName: technologies[j].name,
68
+ toType: technologies[j].entityType,
69
+ relationType: "related_to",
70
+ strength: 0.3,
71
+ });
72
+ }
73
+ }
74
+ }
75
+ return this.deduplicate(results);
76
+ }
77
+ deduplicate(relations) {
78
+ const seen = new Map();
79
+ for (const r of relations) {
80
+ const key = `${r.fromName}:${r.fromType}→${r.toName}:${r.toType}:${r.relationType}`;
81
+ const existing = seen.get(key);
82
+ if (!existing || r.strength > existing.strength) {
83
+ seen.set(key, r);
84
+ }
85
+ }
86
+ return Array.from(seen.values());
87
+ }
88
+ }
89
+ //# sourceMappingURL=relation-inferrer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relation-inferrer.js","sourceRoot":"","sources":["../../src/graph/relation-inferrer.ts"],"names":[],"mappings":"AAWA,MAAM,OAAO,gBAAgB;IAC3B;;;;;OAKG;IACH,KAAK,CACH,QAAyD,EACzD,cAAuC,EAAE;QAEzC,MAAM,OAAO,GAAuB,EAAE,CAAC;QAEvC,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC;QAClE,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC;QACpE,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAClC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,YAAY,IAAI,CAAC,CAAC,UAAU,KAAK,MAAM,CAChE,CAAC;QAEF,+BAA+B;QAC/B,MAAM,MAAM,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;QACrC,MAAM,WAAW,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC;QAC3C,IACE,OAAO,MAAM,KAAK,QAAQ;YAC1B,MAAM,CAAC,IAAI,EAAE;YACb,OAAO,WAAW,KAAK,QAAQ;YAC/B,WAAW,CAAC,IAAI,EAAE,EAClB,CAAC;YACD,OAAO,CAAC,IAAI,CAAC;gBACX,QAAQ,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE;gBACrC,QAAQ,EAAE,QAAQ;gBAClB,MAAM,EAAE,WAAW,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE;gBACxC,MAAM,EAAE,SAAS;gBACjB,YAAY,EAAE,YAAY;gBAC1B,QAAQ,EAAE,GAAG;aACd,CAAC,CAAC;QACL,CAAC;QAED,8DAA8D;QAC9D,IAAI,OAAO,WAAW,KAAK,QAAQ,IAAI,WAAW,CAAC,IAAI,EAAE,EAAE,CAAC;YAC1D,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;gBAC7B,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,QAAQ,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;oBACrD,OAAO,CAAC,IAAI,CAAC;wBACX,QAAQ,EAAE,MAAM,CAAC,IAAI;wBACrB,QAAQ,EAAE,QAAQ;wBAClB,MAAM,EAAE,WAAW,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE;wBACxC,MAAM,EAAE,SAAS;wBACjB,YAAY,EAAE,UAAU;wBACxB,QAAQ,EAAE,GAAG;qBACd,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;QAED,8DAA8D;QAC9D,oFAAoF;QACpF,yEAAyE;QACzE,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;gBAChC,OAAO,CAAC,IAAI,CAAC;oBACX,QAAQ,EAAE,OAAO,CAAC,IAAI;oBACtB,QAAQ,EAAE,SAAS;oBACnB,MAAM,EAAE,IAAI,CAAC,IAAI;oBACjB,MAAM,EAAE,IAAI,CAAC,UAAU;oBACvB,YAAY,EAAE,MAAM;oBACpB,QAAQ,EAAE,GAAG;iBACd,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,mEAAmE;QACnE,0CAA0C;QAC1C,IAAI,YAAY,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;YAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC7C,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBACjD,OAAO,CAAC,IAAI,CAAC;wBACX,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI;wBAC9B,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,UAAU;wBACpC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI;wBAC5B,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,UAAU;wBAClC,YAAY,EAAE,YAAY;wBAC1B,QAAQ,EAAE,GAAG;qBACd,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IACnC,CAAC;IAEO,WAAW,CAAC,SAA6B;QAC/C,MAAM,IAAI,GAAG,IAAI,GAAG,EAA4B,CAAC;QACjD,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;YAC1B,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,YAAY,EAAE,CAAC;YACpF,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC/B,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC,QAAQ,GAAG,QAAQ,CAAC,QAAQ,EAAE,CAAC;gBAChD,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YACnB,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IACnC,CAAC;CACF"}