@knowledgine/core 0.0.1

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 (82) hide show
  1. package/LICENSE +21 -0
  2. package/dist/config.d.ts +13 -0
  3. package/dist/config.d.ts.map +1 -0
  4. package/dist/config.js +30 -0
  5. package/dist/config.js.map +1 -0
  6. package/dist/errors.d.ts +42 -0
  7. package/dist/errors.d.ts.map +1 -0
  8. package/dist/errors.js +101 -0
  9. package/dist/errors.js.map +1 -0
  10. package/dist/extraction/context-analyzer.d.ts +21 -0
  11. package/dist/extraction/context-analyzer.d.ts.map +1 -0
  12. package/dist/extraction/context-analyzer.js +50 -0
  13. package/dist/extraction/context-analyzer.js.map +1 -0
  14. package/dist/extraction/default-patterns.d.ts +21 -0
  15. package/dist/extraction/default-patterns.d.ts.map +1 -0
  16. package/dist/extraction/default-patterns.js +121 -0
  17. package/dist/extraction/default-patterns.js.map +1 -0
  18. package/dist/extraction/pattern-extractor.d.ts +18 -0
  19. package/dist/extraction/pattern-extractor.d.ts.map +1 -0
  20. package/dist/extraction/pattern-extractor.js +182 -0
  21. package/dist/extraction/pattern-extractor.js.map +1 -0
  22. package/dist/extraction/psp-detector.d.ts +29 -0
  23. package/dist/extraction/psp-detector.d.ts.map +1 -0
  24. package/dist/extraction/psp-detector.js +49 -0
  25. package/dist/extraction/psp-detector.js.map +1 -0
  26. package/dist/extraction/rule-based-classifier.d.ts +13 -0
  27. package/dist/extraction/rule-based-classifier.d.ts.map +1 -0
  28. package/dist/extraction/rule-based-classifier.js +35 -0
  29. package/dist/extraction/rule-based-classifier.js.map +1 -0
  30. package/dist/index.d.ts +34 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +32 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/memory/memory-manager.d.ts +21 -0
  35. package/dist/memory/memory-manager.d.ts.map +1 -0
  36. package/dist/memory/memory-manager.js +206 -0
  37. package/dist/memory/memory-manager.js.map +1 -0
  38. package/dist/processing/file-processor.d.ts +15 -0
  39. package/dist/processing/file-processor.d.ts.map +1 -0
  40. package/dist/processing/file-processor.js +38 -0
  41. package/dist/processing/file-processor.js.map +1 -0
  42. package/dist/search/knowledge-searcher.d.ts +25 -0
  43. package/dist/search/knowledge-searcher.d.ts.map +1 -0
  44. package/dist/search/knowledge-searcher.js +45 -0
  45. package/dist/search/knowledge-searcher.js.map +1 -0
  46. package/dist/search/link-generator.d.ts +21 -0
  47. package/dist/search/link-generator.d.ts.map +1 -0
  48. package/dist/search/link-generator.js +131 -0
  49. package/dist/search/link-generator.js.map +1 -0
  50. package/dist/storage/database.d.ts +3 -0
  51. package/dist/storage/database.d.ts.map +1 -0
  52. package/dist/storage/database.js +14 -0
  53. package/dist/storage/database.js.map +1 -0
  54. package/dist/storage/knowledge-repository.d.ts +74 -0
  55. package/dist/storage/knowledge-repository.d.ts.map +1 -0
  56. package/dist/storage/knowledge-repository.js +244 -0
  57. package/dist/storage/knowledge-repository.js.map +1 -0
  58. package/dist/storage/migrations/001_initial.d.ts +3 -0
  59. package/dist/storage/migrations/001_initial.d.ts.map +1 -0
  60. package/dist/storage/migrations/001_initial.js +21 -0
  61. package/dist/storage/migrations/001_initial.js.map +1 -0
  62. package/dist/storage/migrations/002_memory_layers.d.ts +3 -0
  63. package/dist/storage/migrations/002_memory_layers.d.ts.map +1 -0
  64. package/dist/storage/migrations/002_memory_layers.js +55 -0
  65. package/dist/storage/migrations/002_memory_layers.js.map +1 -0
  66. package/dist/storage/migrator.d.ts +24 -0
  67. package/dist/storage/migrator.d.ts.map +1 -0
  68. package/dist/storage/migrator.js +68 -0
  69. package/dist/storage/migrator.js.map +1 -0
  70. package/dist/storage/schema.d.ts +2 -0
  71. package/dist/storage/schema.d.ts.map +1 -0
  72. package/dist/storage/schema.js +79 -0
  73. package/dist/storage/schema.js.map +1 -0
  74. package/dist/types.d.ts +119 -0
  75. package/dist/types.d.ts.map +1 -0
  76. package/dist/types.js +2 -0
  77. package/dist/types.js.map +1 -0
  78. package/dist/utils/code-block-detector.d.ts +25 -0
  79. package/dist/utils/code-block-detector.d.ts.map +1 -0
  80. package/dist/utils/code-block-detector.js +84 -0
  81. package/dist/utils/code-block-detector.js.map +1 -0
  82. package/package.json +53 -0
@@ -0,0 +1,244 @@
1
+ import { ValidationError, DatabaseError, KnowledgeNotFoundError, FTSIndexError, } from "../errors.js";
2
+ import { createHash } from "crypto";
3
+ export class KnowledgeRepository {
4
+ db;
5
+ constructor(db) {
6
+ this.db = db;
7
+ }
8
+ computeHash(content) {
9
+ return createHash("sha256").update(content).digest("hex");
10
+ }
11
+ validateNoteData(data) {
12
+ if (!data.filePath || typeof data.filePath !== "string" || data.filePath.trim() === "") {
13
+ throw new ValidationError("filePath", data.filePath, "File path is required and must be a non-empty string");
14
+ }
15
+ if (!data.title || typeof data.title !== "string" || data.title.trim() === "") {
16
+ throw new ValidationError("title", data.title, "Title is required and must be a non-empty string");
17
+ }
18
+ if (!data.content || typeof data.content !== "string") {
19
+ throw new ValidationError("content", data.content, "Content is required and must be a string");
20
+ }
21
+ }
22
+ saveNote(data) {
23
+ this.validateNoteData(data);
24
+ try {
25
+ const existing = this.getNoteByPath(data.filePath);
26
+ const now = new Date().toISOString();
27
+ const contentHash = this.computeHash(data.content);
28
+ const frontmatterJson = data.frontmatter && Object.keys(data.frontmatter).length > 0
29
+ ? JSON.stringify(data.frontmatter)
30
+ : null;
31
+ if (existing) {
32
+ // Skip update if content hasn't changed
33
+ if (existing.content_hash === contentHash) {
34
+ return existing.id;
35
+ }
36
+ const stmt = this.db.prepare(`
37
+ UPDATE knowledge_notes
38
+ SET title = ?, content = ?, frontmatter_json = ?,
39
+ updated_at = ?, content_hash = ?
40
+ WHERE id = ?
41
+ `);
42
+ stmt.run(data.title, data.content, frontmatterJson, now, contentHash, existing.id);
43
+ return existing.id;
44
+ }
45
+ else {
46
+ const stmt = this.db.prepare(`
47
+ INSERT INTO knowledge_notes (
48
+ file_path, title, content, frontmatter_json,
49
+ created_at, updated_at, content_hash
50
+ ) VALUES (?, ?, ?, ?, ?, ?, ?)
51
+ `);
52
+ const info = stmt.run(data.filePath, data.title, data.content, frontmatterJson, data.createdAt || now, now, contentHash);
53
+ return Number(info.lastInsertRowid);
54
+ }
55
+ }
56
+ catch (error) {
57
+ if (error instanceof ValidationError)
58
+ throw error;
59
+ throw new DatabaseError("saveNote", error, { filePath: data.filePath });
60
+ }
61
+ }
62
+ getNoteById(id) {
63
+ const stmt = this.db.prepare("SELECT * FROM knowledge_notes WHERE id = ?");
64
+ return stmt.get(id);
65
+ }
66
+ getNoteByPath(filePath) {
67
+ const stmt = this.db.prepare("SELECT * FROM knowledge_notes WHERE file_path = ?");
68
+ return stmt.get(filePath);
69
+ }
70
+ getNoteByIdOrThrow(id) {
71
+ const note = this.getNoteById(id);
72
+ if (!note)
73
+ throw new KnowledgeNotFoundError(id, "id");
74
+ return note;
75
+ }
76
+ getNoteByPathOrThrow(filePath) {
77
+ const note = this.getNoteByPath(filePath);
78
+ if (!note)
79
+ throw new KnowledgeNotFoundError(filePath, "path");
80
+ return note;
81
+ }
82
+ searchNotes(query, limit = 50) {
83
+ try {
84
+ const stmt = this.db.prepare(`
85
+ SELECT n.*
86
+ FROM knowledge_notes n
87
+ JOIN knowledge_notes_fts fts ON n.id = fts.rowid
88
+ WHERE knowledge_notes_fts MATCH ?
89
+ ORDER BY rank
90
+ LIMIT ?
91
+ `);
92
+ return stmt.all(query, limit);
93
+ }
94
+ catch (error) {
95
+ throw new FTSIndexError("search", error, { query, limit });
96
+ }
97
+ }
98
+ deleteNoteById(id) {
99
+ try {
100
+ const stmt = this.db.prepare("DELETE FROM knowledge_notes WHERE id = ?");
101
+ const info = stmt.run(id);
102
+ return info.changes > 0;
103
+ }
104
+ catch (error) {
105
+ throw new DatabaseError("deleteNoteById", error, { id });
106
+ }
107
+ }
108
+ deleteNoteByPath(path) {
109
+ try {
110
+ const stmt = this.db.prepare("DELETE FROM knowledge_notes WHERE file_path = ?");
111
+ const info = stmt.run(path);
112
+ return info.changes > 0;
113
+ }
114
+ catch (error) {
115
+ throw new DatabaseError("deleteNoteByPath", error, { path });
116
+ }
117
+ }
118
+ savePatterns(noteId, patterns) {
119
+ if (!noteId || typeof noteId !== "number" || noteId <= 0) {
120
+ throw new ValidationError("noteId", noteId, "Note ID must be a positive number");
121
+ }
122
+ if (!Array.isArray(patterns)) {
123
+ throw new ValidationError("patterns", patterns, "Patterns must be an array");
124
+ }
125
+ try {
126
+ const deleteStmt = this.db.prepare("DELETE FROM extracted_patterns WHERE note_id = ?");
127
+ deleteStmt.run(noteId);
128
+ const insertStmt = this.db.prepare(`
129
+ INSERT INTO extracted_patterns (
130
+ note_id, pattern_type, content, confidence,
131
+ context, line_number, created_at
132
+ ) VALUES (?, ?, ?, ?, ?, ?, ?)
133
+ `);
134
+ const now = new Date().toISOString();
135
+ for (const pattern of patterns) {
136
+ insertStmt.run(noteId, pattern.type, pattern.content, pattern.confidence, pattern.context ?? null, pattern.lineNumber ?? null, now);
137
+ }
138
+ }
139
+ catch (error) {
140
+ if (error instanceof ValidationError)
141
+ throw error;
142
+ throw new DatabaseError("savePatterns", error, { noteId });
143
+ }
144
+ }
145
+ getPatternsByNoteId(noteId) {
146
+ const stmt = this.db.prepare("SELECT * FROM extracted_patterns WHERE note_id = ? ORDER BY line_number");
147
+ return stmt.all(noteId);
148
+ }
149
+ saveProblemSolutionPairs(pairs) {
150
+ const stmt = this.db.prepare(`
151
+ INSERT INTO problem_solution_pairs (
152
+ problem_pattern_id, solution_pattern_id, relevance_score, created_at
153
+ ) VALUES (?, ?, ?, ?)
154
+ `);
155
+ const now = new Date().toISOString();
156
+ for (const pair of pairs) {
157
+ stmt.run(pair.problemPatternId, pair.solutionPatternId, pair.relevanceScore, now);
158
+ }
159
+ }
160
+ saveNoteLinks(links) {
161
+ const stmt = this.db.prepare(`
162
+ INSERT OR REPLACE INTO note_links (
163
+ source_note_id, target_note_id, link_type, similarity, created_at
164
+ ) VALUES (?, ?, ?, ?, ?)
165
+ `);
166
+ const now = new Date().toISOString();
167
+ for (const link of links) {
168
+ stmt.run(link.sourceNoteId, link.targetNoteId, link.linkType, link.similarity ?? null, now);
169
+ }
170
+ }
171
+ getNoteLinks(noteId) {
172
+ const stmt = this.db.prepare(`
173
+ SELECT target_note_id as targetNoteId, link_type as linkType, similarity
174
+ FROM note_links WHERE source_note_id = ?
175
+ ORDER BY similarity DESC
176
+ `);
177
+ return stmt.all(noteId);
178
+ }
179
+ getProblemSolutionPairsByNoteId(noteId) {
180
+ // Join through extracted_patterns to find pairs associated with this note's patterns
181
+ const stmt = this.db.prepare(`
182
+ SELECT psp.id,
183
+ ep_problem.note_id as problemNoteId,
184
+ ep_solution.note_id as solutionNoteId,
185
+ ep_problem.content as problemPattern,
186
+ ep_solution.content as solutionPattern,
187
+ psp.relevance_score as confidence
188
+ FROM problem_solution_pairs psp
189
+ JOIN extracted_patterns ep_problem ON psp.problem_pattern_id = ep_problem.id
190
+ JOIN extracted_patterns ep_solution ON psp.solution_pattern_id = ep_solution.id
191
+ WHERE ep_problem.note_id = ? OR ep_solution.note_id = ?
192
+ `);
193
+ return stmt.all(noteId, noteId);
194
+ }
195
+ findNotesByTagSimilarity(noteId, tags, limit) {
196
+ // Search notes that share tags via frontmatter_json
197
+ const conditions = tags.map(() => "n.frontmatter_json LIKE ?").join(" OR ");
198
+ const params = tags.map((tag) => `%"${tag}"%`);
199
+ const stmt = this.db.prepare(`
200
+ SELECT n.* FROM knowledge_notes n
201
+ WHERE n.id != ? AND (${conditions})
202
+ LIMIT ?
203
+ `);
204
+ return stmt.all(noteId, ...params, limit);
205
+ }
206
+ findNotesByTitleKeywords(noteId, keywords, limit) {
207
+ const conditions = keywords.map(() => "n.title LIKE ?").join(" OR ");
208
+ const params = keywords.map((kw) => `%${kw}%`);
209
+ const stmt = this.db.prepare(`
210
+ SELECT n.* FROM knowledge_notes n
211
+ WHERE n.id != ? AND (${conditions})
212
+ LIMIT ?
213
+ `);
214
+ return stmt.all(noteId, ...params, limit);
215
+ }
216
+ findNotesByTimeProximity(noteId, createdAt, days, limit) {
217
+ const stmt = this.db.prepare(`
218
+ SELECT * FROM knowledge_notes
219
+ WHERE id != ?
220
+ AND ABS(julianday(created_at) - julianday(?)) <= ?
221
+ ORDER BY ABS(julianday(created_at) - julianday(?))
222
+ LIMIT ?
223
+ `);
224
+ return stmt.all(noteId, createdAt, days, createdAt, limit);
225
+ }
226
+ getStats() {
227
+ const totalNotes = this.db.prepare("SELECT COUNT(*) as count FROM knowledge_notes").get().count;
228
+ const totalPatterns = this.db.prepare("SELECT COUNT(*) as count FROM extracted_patterns").get().count;
229
+ const totalLinks = this.db.prepare("SELECT COUNT(*) as count FROM note_links").get().count;
230
+ const totalPairs = this.db.prepare("SELECT COUNT(*) as count FROM problem_solution_pairs").get().count;
231
+ const typeRows = this.db
232
+ .prepare("SELECT pattern_type, COUNT(*) as count FROM extracted_patterns GROUP BY pattern_type")
233
+ .all();
234
+ const patternsByType = {};
235
+ for (const row of typeRows) {
236
+ patternsByType[row.pattern_type] = row.count;
237
+ }
238
+ return { totalNotes, totalPatterns, totalLinks, totalPairs, patternsByType };
239
+ }
240
+ close() {
241
+ this.db.close();
242
+ }
243
+ }
244
+ //# sourceMappingURL=knowledge-repository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"knowledge-repository.js","sourceRoot":"","sources":["../../src/storage/knowledge-repository.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Migration } from "../migrator.js";
2
+ export declare const migration001: Migration;
3
+ //# sourceMappingURL=001_initial.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"001_initial.d.ts","sourceRoot":"","sources":["../../../src/storage/migrations/001_initial.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAGhD,eAAO,MAAM,YAAY,EAAE,SAkB1B,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { SCHEMA_SQL } from "../schema.js";
2
+ export const migration001 = {
3
+ version: 1,
4
+ name: "initial_schema",
5
+ up: (db) => {
6
+ db.exec(SCHEMA_SQL);
7
+ },
8
+ down: (db) => {
9
+ db.exec(`
10
+ DROP TRIGGER IF EXISTS knowledge_notes_au;
11
+ DROP TRIGGER IF EXISTS knowledge_notes_ad;
12
+ DROP TRIGGER IF EXISTS knowledge_notes_ai;
13
+ DROP TABLE IF EXISTS knowledge_notes_fts;
14
+ DROP TABLE IF EXISTS note_links;
15
+ DROP TABLE IF EXISTS problem_solution_pairs;
16
+ DROP TABLE IF EXISTS extracted_patterns;
17
+ DROP TABLE IF EXISTS knowledge_notes;
18
+ `);
19
+ },
20
+ };
21
+ //# sourceMappingURL=001_initial.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"001_initial.js","sourceRoot":"","sources":["../../../src/storage/migrations/001_initial.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,CAAC,MAAM,YAAY,GAAc;IACrC,OAAO,EAAE,CAAC;IACV,IAAI,EAAE,gBAAgB;IACtB,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE;QACT,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACtB,CAAC;IACD,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE;QACX,EAAE,CAAC,IAAI,CAAC;;;;;;;;;KASP,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Migration } from "../migrator.js";
2
+ export declare const migration002: Migration;
3
+ //# sourceMappingURL=002_memory_layers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"002_memory_layers.d.ts","sourceRoot":"","sources":["../../../src/storage/migrations/002_memory_layers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAyChD,eAAO,MAAM,YAAY,EAAE,SAe1B,CAAC"}
@@ -0,0 +1,55 @@
1
+ const MEMORY_LAYERS_SQL = `
2
+ CREATE TABLE memory_entries (
3
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
4
+ note_id INTEGER,
5
+ layer TEXT NOT NULL CHECK(layer IN ('episodic', 'semantic', 'procedural')),
6
+ content TEXT NOT NULL,
7
+ summary TEXT,
8
+ access_count INTEGER NOT NULL DEFAULT 0,
9
+ last_accessed_at TEXT,
10
+ promoted_from INTEGER,
11
+ created_at TEXT NOT NULL,
12
+ updated_at TEXT,
13
+ metadata_json TEXT,
14
+ FOREIGN KEY (note_id) REFERENCES knowledge_notes(id) ON DELETE SET NULL,
15
+ FOREIGN KEY (promoted_from) REFERENCES memory_entries(id) ON DELETE SET NULL
16
+ );
17
+
18
+ CREATE INDEX idx_memory_entries_layer ON memory_entries(layer);
19
+ CREATE INDEX idx_memory_entries_note_id ON memory_entries(note_id);
20
+ CREATE INDEX idx_memory_entries_access_count ON memory_entries(access_count);
21
+
22
+ CREATE VIRTUAL TABLE memory_entries_fts USING fts5(
23
+ content, summary, content='memory_entries', content_rowid='id', tokenize='trigram'
24
+ );
25
+
26
+ CREATE TRIGGER memory_entries_ai AFTER INSERT ON memory_entries BEGIN
27
+ INSERT INTO memory_entries_fts(rowid, content, summary) VALUES (new.id, new.content, COALESCE(new.summary, ''));
28
+ END;
29
+
30
+ CREATE TRIGGER memory_entries_ad AFTER DELETE ON memory_entries BEGIN
31
+ INSERT INTO memory_entries_fts(memory_entries_fts, rowid, content, summary) VALUES('delete', old.id, old.content, COALESCE(old.summary, ''));
32
+ END;
33
+
34
+ CREATE TRIGGER memory_entries_au AFTER UPDATE ON memory_entries BEGIN
35
+ INSERT INTO memory_entries_fts(memory_entries_fts, rowid, content, summary) VALUES('delete', old.id, old.content, COALESCE(old.summary, ''));
36
+ INSERT INTO memory_entries_fts(rowid, content, summary) VALUES (new.id, new.content, COALESCE(new.summary, ''));
37
+ END;
38
+ `;
39
+ export const migration002 = {
40
+ version: 2,
41
+ name: "memory_layers",
42
+ up: (db) => {
43
+ db.exec(MEMORY_LAYERS_SQL);
44
+ },
45
+ down: (db) => {
46
+ db.exec(`
47
+ DROP TRIGGER IF EXISTS memory_entries_au;
48
+ DROP TRIGGER IF EXISTS memory_entries_ad;
49
+ DROP TRIGGER IF EXISTS memory_entries_ai;
50
+ DROP TABLE IF EXISTS memory_entries_fts;
51
+ DROP TABLE IF EXISTS memory_entries;
52
+ `);
53
+ },
54
+ };
55
+ //# sourceMappingURL=002_memory_layers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"002_memory_layers.js","sourceRoot":"","sources":["../../../src/storage/migrations/002_memory_layers.ts"],"names":[],"mappings":"AAEA,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqCzB,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAc;IACrC,OAAO,EAAE,CAAC;IACV,IAAI,EAAE,eAAe;IACrB,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE;QACT,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAC7B,CAAC;IACD,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE;QACX,EAAE,CAAC,IAAI,CAAC;;;;;;KAMP,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
@@ -0,0 +1,24 @@
1
+ import type Database from "better-sqlite3";
2
+ export interface Migration {
3
+ version: number;
4
+ name: string;
5
+ up: (db: Database.Database) => void;
6
+ down: (db: Database.Database) => void;
7
+ }
8
+ export interface MigrationStatus {
9
+ version: number;
10
+ name: string;
11
+ applied: boolean;
12
+ appliedAt?: string;
13
+ }
14
+ export declare class Migrator {
15
+ private db;
16
+ private migrations;
17
+ constructor(db: Database.Database, migrations: Migration[]);
18
+ private ensureSchemaVersionTable;
19
+ getCurrentVersion(): number;
20
+ migrate(): void;
21
+ rollback(toVersion: number): void;
22
+ status(): MigrationStatus[];
23
+ }
24
+ //# sourceMappingURL=migrator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrator.d.ts","sourceRoot":"","sources":["../../src/storage/migrator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,KAAK,IAAI,CAAC;IACpC,IAAI,EAAE,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,KAAK,IAAI,CAAC;CACvC;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,QAAQ;IAEjB,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,UAAU;gBADV,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,UAAU,EAAE,SAAS,EAAE;IAKjC,OAAO,CAAC,wBAAwB;IAUhC,iBAAiB,IAAI,MAAM;IAO3B,OAAO,IAAI,IAAI;IAoBf,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAkBjC,MAAM,IAAI,eAAe,EAAE;CAkB5B"}
@@ -0,0 +1,68 @@
1
+ export class Migrator {
2
+ db;
3
+ migrations;
4
+ constructor(db, migrations) {
5
+ this.db = db;
6
+ this.migrations = migrations;
7
+ this.ensureSchemaVersionTable();
8
+ }
9
+ ensureSchemaVersionTable() {
10
+ this.db.exec(`
11
+ CREATE TABLE IF NOT EXISTS schema_version (
12
+ version INTEGER PRIMARY KEY,
13
+ name TEXT NOT NULL,
14
+ applied_at TEXT NOT NULL
15
+ )
16
+ `);
17
+ }
18
+ getCurrentVersion() {
19
+ const row = this.db.prepare("SELECT MAX(version) as version FROM schema_version").get();
20
+ return row?.version ?? 0;
21
+ }
22
+ migrate() {
23
+ const currentVersion = this.getCurrentVersion();
24
+ const pending = this.migrations
25
+ .filter((m) => m.version > currentVersion)
26
+ .sort((a, b) => a.version - b.version);
27
+ if (pending.length === 0)
28
+ return;
29
+ const runMigrations = this.db.transaction(() => {
30
+ for (const migration of pending) {
31
+ migration.up(this.db);
32
+ this.db
33
+ .prepare("INSERT INTO schema_version (version, name, applied_at) VALUES (?, ?, ?)")
34
+ .run(migration.version, migration.name, new Date().toISOString());
35
+ }
36
+ });
37
+ runMigrations();
38
+ }
39
+ rollback(toVersion) {
40
+ const currentVersion = this.getCurrentVersion();
41
+ const toRollback = this.migrations
42
+ .filter((m) => m.version > toVersion && m.version <= currentVersion)
43
+ .sort((a, b) => b.version - a.version);
44
+ if (toRollback.length === 0)
45
+ return;
46
+ const runRollbacks = this.db.transaction(() => {
47
+ for (const migration of toRollback) {
48
+ migration.down(this.db);
49
+ this.db.prepare("DELETE FROM schema_version WHERE version = ?").run(migration.version);
50
+ }
51
+ });
52
+ runRollbacks();
53
+ }
54
+ status() {
55
+ const applied = new Map();
56
+ const rows = this.db.prepare("SELECT version, applied_at FROM schema_version").all();
57
+ for (const row of rows) {
58
+ applied.set(row.version, row.applied_at);
59
+ }
60
+ return this.migrations.map((m) => ({
61
+ version: m.version,
62
+ name: m.name,
63
+ applied: applied.has(m.version),
64
+ appliedAt: applied.get(m.version),
65
+ }));
66
+ }
67
+ }
68
+ //# sourceMappingURL=migrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrator.js","sourceRoot":"","sources":["../../src/storage/migrator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const SCHEMA_SQL = "\n-- 1. knowledge_notes\nCREATE TABLE IF NOT EXISTS knowledge_notes (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n file_path TEXT UNIQUE NOT NULL,\n title TEXT NOT NULL,\n content TEXT NOT NULL,\n frontmatter_json TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT,\n content_hash TEXT\n);\n\n-- 2. extracted_patterns\nCREATE TABLE IF NOT EXISTS extracted_patterns (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n note_id INTEGER NOT NULL,\n pattern_type TEXT NOT NULL CHECK(pattern_type IN ('problem','solution','learning','time')),\n content TEXT NOT NULL,\n confidence REAL NOT NULL,\n context TEXT,\n line_number INTEGER,\n created_at TEXT NOT NULL,\n FOREIGN KEY (note_id) REFERENCES knowledge_notes(id) ON DELETE CASCADE\n);\n\n-- 3. problem_solution_pairs\nCREATE TABLE IF NOT EXISTS problem_solution_pairs (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n problem_pattern_id INTEGER NOT NULL,\n solution_pattern_id INTEGER NOT NULL,\n relevance_score REAL NOT NULL,\n created_at TEXT NOT NULL,\n FOREIGN KEY (problem_pattern_id) REFERENCES extracted_patterns(id) ON DELETE CASCADE,\n FOREIGN KEY (solution_pattern_id) REFERENCES extracted_patterns(id) ON DELETE CASCADE\n);\n\n-- 4. note_links\nCREATE TABLE IF NOT EXISTS note_links (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n source_note_id INTEGER NOT NULL,\n target_note_id INTEGER NOT NULL,\n link_type TEXT NOT NULL,\n similarity REAL,\n created_at TEXT NOT NULL,\n FOREIGN KEY (source_note_id) REFERENCES knowledge_notes(id) ON DELETE CASCADE,\n FOREIGN KEY (target_note_id) REFERENCES knowledge_notes(id) ON DELETE CASCADE,\n UNIQUE(source_note_id, target_note_id)\n);\n\n-- 5. FTS5 virtual table\nCREATE VIRTUAL TABLE IF NOT EXISTS knowledge_notes_fts USING fts5(\n title,\n content,\n content='knowledge_notes',\n content_rowid='id',\n tokenize='trigram'\n);\n\n-- FTS5 triggers\nCREATE TRIGGER IF NOT EXISTS knowledge_notes_ai AFTER INSERT ON knowledge_notes BEGIN\n INSERT INTO knowledge_notes_fts(rowid, title, content) VALUES (new.id, new.title, new.content);\nEND;\n\nCREATE TRIGGER IF NOT EXISTS knowledge_notes_ad AFTER DELETE ON knowledge_notes BEGIN\n INSERT INTO knowledge_notes_fts(knowledge_notes_fts, rowid, title, content) VALUES('delete', old.id, old.title, old.content);\nEND;\n\nCREATE TRIGGER IF NOT EXISTS knowledge_notes_au AFTER UPDATE ON knowledge_notes BEGIN\n INSERT INTO knowledge_notes_fts(knowledge_notes_fts, rowid, title, content) VALUES('delete', old.id, old.title, old.content);\n INSERT INTO knowledge_notes_fts(rowid, title, content) VALUES (new.id, new.title, new.content);\nEND;\n\n-- Indexes\nCREATE INDEX IF NOT EXISTS idx_knowledge_notes_created_at ON knowledge_notes(created_at);\nCREATE INDEX IF NOT EXISTS idx_extracted_patterns_note_id ON extracted_patterns(note_id);\nCREATE INDEX IF NOT EXISTS idx_extracted_patterns_type ON extracted_patterns(pattern_type);\n";
2
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/storage/schema.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,y1FA6EtB,CAAC"}
@@ -0,0 +1,79 @@
1
+ export const SCHEMA_SQL = `
2
+ -- 1. knowledge_notes
3
+ CREATE TABLE IF NOT EXISTS knowledge_notes (
4
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
5
+ file_path TEXT UNIQUE NOT NULL,
6
+ title TEXT NOT NULL,
7
+ content TEXT NOT NULL,
8
+ frontmatter_json TEXT,
9
+ created_at TEXT NOT NULL,
10
+ updated_at TEXT,
11
+ content_hash TEXT
12
+ );
13
+
14
+ -- 2. extracted_patterns
15
+ CREATE TABLE IF NOT EXISTS extracted_patterns (
16
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
17
+ note_id INTEGER NOT NULL,
18
+ pattern_type TEXT NOT NULL CHECK(pattern_type IN ('problem','solution','learning','time')),
19
+ content TEXT NOT NULL,
20
+ confidence REAL NOT NULL,
21
+ context TEXT,
22
+ line_number INTEGER,
23
+ created_at TEXT NOT NULL,
24
+ FOREIGN KEY (note_id) REFERENCES knowledge_notes(id) ON DELETE CASCADE
25
+ );
26
+
27
+ -- 3. problem_solution_pairs
28
+ CREATE TABLE IF NOT EXISTS problem_solution_pairs (
29
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
30
+ problem_pattern_id INTEGER NOT NULL,
31
+ solution_pattern_id INTEGER NOT NULL,
32
+ relevance_score REAL NOT NULL,
33
+ created_at TEXT NOT NULL,
34
+ FOREIGN KEY (problem_pattern_id) REFERENCES extracted_patterns(id) ON DELETE CASCADE,
35
+ FOREIGN KEY (solution_pattern_id) REFERENCES extracted_patterns(id) ON DELETE CASCADE
36
+ );
37
+
38
+ -- 4. note_links
39
+ CREATE TABLE IF NOT EXISTS note_links (
40
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
41
+ source_note_id INTEGER NOT NULL,
42
+ target_note_id INTEGER NOT NULL,
43
+ link_type TEXT NOT NULL,
44
+ similarity REAL,
45
+ created_at TEXT NOT NULL,
46
+ FOREIGN KEY (source_note_id) REFERENCES knowledge_notes(id) ON DELETE CASCADE,
47
+ FOREIGN KEY (target_note_id) REFERENCES knowledge_notes(id) ON DELETE CASCADE,
48
+ UNIQUE(source_note_id, target_note_id)
49
+ );
50
+
51
+ -- 5. FTS5 virtual table
52
+ CREATE VIRTUAL TABLE IF NOT EXISTS knowledge_notes_fts USING fts5(
53
+ title,
54
+ content,
55
+ content='knowledge_notes',
56
+ content_rowid='id',
57
+ tokenize='trigram'
58
+ );
59
+
60
+ -- FTS5 triggers
61
+ CREATE TRIGGER IF NOT EXISTS knowledge_notes_ai AFTER INSERT ON knowledge_notes BEGIN
62
+ INSERT INTO knowledge_notes_fts(rowid, title, content) VALUES (new.id, new.title, new.content);
63
+ END;
64
+
65
+ CREATE TRIGGER IF NOT EXISTS knowledge_notes_ad AFTER DELETE ON knowledge_notes BEGIN
66
+ INSERT INTO knowledge_notes_fts(knowledge_notes_fts, rowid, title, content) VALUES('delete', old.id, old.title, old.content);
67
+ END;
68
+
69
+ CREATE TRIGGER IF NOT EXISTS knowledge_notes_au AFTER UPDATE ON knowledge_notes BEGIN
70
+ INSERT INTO knowledge_notes_fts(knowledge_notes_fts, rowid, title, content) VALUES('delete', old.id, old.title, old.content);
71
+ INSERT INTO knowledge_notes_fts(rowid, title, content) VALUES (new.id, new.title, new.content);
72
+ END;
73
+
74
+ -- Indexes
75
+ CREATE INDEX IF NOT EXISTS idx_knowledge_notes_created_at ON knowledge_notes(created_at);
76
+ CREATE INDEX IF NOT EXISTS idx_extracted_patterns_note_id ON extracted_patterns(note_id);
77
+ CREATE INDEX IF NOT EXISTS idx_extracted_patterns_type ON extracted_patterns(pattern_type);
78
+ `;
79
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/storage/schema.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6EzB,CAAC"}