@vpxa/kb 0.1.1 → 0.1.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 (138) hide show
  1. package/README.md +3 -3
  2. package/package.json +1 -1
  3. package/packages/analyzers/dist/blast-radius-analyzer.js +13 -114
  4. package/packages/analyzers/dist/dependency-analyzer.js +11 -425
  5. package/packages/analyzers/dist/diagram-generator.js +4 -86
  6. package/packages/analyzers/dist/entry-point-analyzer.js +5 -239
  7. package/packages/analyzers/dist/index.js +1 -23
  8. package/packages/analyzers/dist/knowledge-producer.js +24 -113
  9. package/packages/analyzers/dist/pattern-analyzer.js +5 -359
  10. package/packages/analyzers/dist/regex-call-graph.js +1 -428
  11. package/packages/analyzers/dist/structure-analyzer.js +4 -258
  12. package/packages/analyzers/dist/symbol-analyzer.js +13 -442
  13. package/packages/analyzers/dist/ts-call-graph.js +1 -160
  14. package/packages/analyzers/dist/types.js +0 -1
  15. package/packages/chunker/dist/call-graph-extractor.js +1 -90
  16. package/packages/chunker/dist/chunker-factory.js +1 -36
  17. package/packages/chunker/dist/chunker.interface.js +0 -1
  18. package/packages/chunker/dist/code-chunker.js +14 -134
  19. package/packages/chunker/dist/generic-chunker.js +5 -72
  20. package/packages/chunker/dist/index.js +1 -21
  21. package/packages/chunker/dist/markdown-chunker.js +7 -119
  22. package/packages/chunker/dist/treesitter-chunker.js +8 -234
  23. package/packages/cli/dist/commands/analyze.js +3 -112
  24. package/packages/cli/dist/commands/context-cmds.js +1 -155
  25. package/packages/cli/dist/commands/environment.js +2 -204
  26. package/packages/cli/dist/commands/execution.js +1 -137
  27. package/packages/cli/dist/commands/graph.js +7 -81
  28. package/packages/cli/dist/commands/init.js +9 -87
  29. package/packages/cli/dist/commands/knowledge.js +1 -139
  30. package/packages/cli/dist/commands/search.js +8 -267
  31. package/packages/cli/dist/commands/system.js +4 -241
  32. package/packages/cli/dist/commands/workspace.js +2 -388
  33. package/packages/cli/dist/context.js +1 -14
  34. package/packages/cli/dist/helpers.js +3 -458
  35. package/packages/cli/dist/index.d.ts +1 -1
  36. package/packages/cli/dist/index.js +3 -69
  37. package/packages/cli/dist/kb-init.js +1 -82
  38. package/packages/cli/dist/types.js +0 -1
  39. package/packages/core/dist/constants.js +1 -43
  40. package/packages/core/dist/content-detector.js +1 -79
  41. package/packages/core/dist/errors.js +1 -40
  42. package/packages/core/dist/index.js +1 -9
  43. package/packages/core/dist/logger.js +1 -34
  44. package/packages/core/dist/types.js +0 -1
  45. package/packages/embeddings/dist/embedder.interface.js +0 -1
  46. package/packages/embeddings/dist/index.js +1 -5
  47. package/packages/embeddings/dist/onnx-embedder.js +1 -82
  48. package/packages/indexer/dist/file-hasher.js +1 -13
  49. package/packages/indexer/dist/filesystem-crawler.js +1 -125
  50. package/packages/indexer/dist/graph-extractor.js +1 -111
  51. package/packages/indexer/dist/incremental-indexer.js +1 -278
  52. package/packages/indexer/dist/index.js +1 -14
  53. package/packages/server/dist/api.js +1 -9
  54. package/packages/server/dist/config.js +1 -75
  55. package/packages/server/dist/curated-manager.js +9 -356
  56. package/packages/server/dist/index.js +1 -134
  57. package/packages/server/dist/replay-interceptor.js +1 -38
  58. package/packages/server/dist/resources/resources.js +2 -40
  59. package/packages/server/dist/server.js +1 -247
  60. package/packages/server/dist/tools/analyze.tools.js +1 -288
  61. package/packages/server/dist/tools/forge.tools.js +11 -499
  62. package/packages/server/dist/tools/forget.tool.js +3 -39
  63. package/packages/server/dist/tools/graph.tool.js +5 -110
  64. package/packages/server/dist/tools/list.tool.js +5 -53
  65. package/packages/server/dist/tools/lookup.tool.js +8 -51
  66. package/packages/server/dist/tools/onboard.tool.js +2 -112
  67. package/packages/server/dist/tools/produce.tool.js +4 -74
  68. package/packages/server/dist/tools/read.tool.js +4 -47
  69. package/packages/server/dist/tools/reindex.tool.js +2 -70
  70. package/packages/server/dist/tools/remember.tool.js +3 -42
  71. package/packages/server/dist/tools/replay.tool.js +6 -88
  72. package/packages/server/dist/tools/search.tool.js +17 -327
  73. package/packages/server/dist/tools/status.tool.js +3 -68
  74. package/packages/server/dist/tools/toolkit.tools.js +20 -1673
  75. package/packages/server/dist/tools/update.tool.js +3 -39
  76. package/packages/server/dist/tools/utility.tools.js +19 -456
  77. package/packages/store/dist/graph-store.interface.js +0 -1
  78. package/packages/store/dist/index.js +1 -9
  79. package/packages/store/dist/lance-store.js +1 -258
  80. package/packages/store/dist/sqlite-graph-store.js +8 -309
  81. package/packages/store/dist/store-factory.js +1 -14
  82. package/packages/store/dist/store.interface.js +0 -1
  83. package/packages/tools/dist/batch.js +1 -45
  84. package/packages/tools/dist/changelog.js +2 -112
  85. package/packages/tools/dist/check.js +2 -59
  86. package/packages/tools/dist/checkpoint.js +2 -43
  87. package/packages/tools/dist/codemod.js +2 -69
  88. package/packages/tools/dist/compact.js +3 -60
  89. package/packages/tools/dist/data-transform.js +1 -124
  90. package/packages/tools/dist/dead-symbols.js +2 -71
  91. package/packages/tools/dist/delegate.js +3 -128
  92. package/packages/tools/dist/diff-parse.js +3 -153
  93. package/packages/tools/dist/digest.js +7 -242
  94. package/packages/tools/dist/encode.js +1 -46
  95. package/packages/tools/dist/env-info.js +1 -58
  96. package/packages/tools/dist/eval.js +3 -79
  97. package/packages/tools/dist/evidence-map.js +3 -203
  98. package/packages/tools/dist/file-summary.js +2 -106
  99. package/packages/tools/dist/file-walk.js +1 -75
  100. package/packages/tools/dist/find-examples.js +3 -48
  101. package/packages/tools/dist/find.js +1 -120
  102. package/packages/tools/dist/forge-classify.js +2 -319
  103. package/packages/tools/dist/forge-ground.js +1 -184
  104. package/packages/tools/dist/git-context.js +3 -46
  105. package/packages/tools/dist/graph-query.js +1 -194
  106. package/packages/tools/dist/health.js +1 -118
  107. package/packages/tools/dist/http-request.js +1 -58
  108. package/packages/tools/dist/index.js +1 -273
  109. package/packages/tools/dist/lane.js +7 -227
  110. package/packages/tools/dist/measure.js +2 -119
  111. package/packages/tools/dist/onboard.js +42 -1136
  112. package/packages/tools/dist/parse-output.js +2 -158
  113. package/packages/tools/dist/process-manager.js +1 -69
  114. package/packages/tools/dist/queue.js +2 -126
  115. package/packages/tools/dist/regex-test.js +1 -39
  116. package/packages/tools/dist/rename.js +2 -70
  117. package/packages/tools/dist/replay.js +6 -108
  118. package/packages/tools/dist/schema-validate.js +1 -141
  119. package/packages/tools/dist/scope-map.js +1 -72
  120. package/packages/tools/dist/snippet.js +1 -80
  121. package/packages/tools/dist/stash.js +2 -60
  122. package/packages/tools/dist/stratum-card.js +5 -238
  123. package/packages/tools/dist/symbol.js +3 -87
  124. package/packages/tools/dist/test-run.js +2 -55
  125. package/packages/tools/dist/text-utils.js +2 -31
  126. package/packages/tools/dist/time-utils.js +1 -135
  127. package/packages/tools/dist/trace.js +2 -114
  128. package/packages/tools/dist/truncation.js +10 -41
  129. package/packages/tools/dist/watch.js +1 -61
  130. package/packages/tools/dist/web-fetch.js +9 -244
  131. package/packages/tools/dist/web-search.js +1 -46
  132. package/packages/tools/dist/workset.js +2 -77
  133. package/packages/tui/dist/App.js +260 -52468
  134. package/packages/tui/dist/index.js +286 -54551
  135. package/packages/tui/dist/panels/CuratedPanel.js +211 -34291
  136. package/packages/tui/dist/panels/LogPanel.js +259 -51703
  137. package/packages/tui/dist/panels/SearchPanel.js +212 -34824
  138. package/packages/tui/dist/panels/StatusPanel.js +211 -34304
@@ -1,258 +1 @@
1
- import { EMBEDDING_DEFAULTS, SEARCH_DEFAULTS, STORE_DEFAULTS } from "@kb/core";
2
- import { connect, Index } from "@lancedb/lancedb";
3
- const SAFE_FILTER_VALUE = /^[\w.\-/ ]+$/;
4
- function sanitizeFilterValue(value, fieldName) {
5
- if (!SAFE_FILTER_VALUE.test(value)) {
6
- throw new Error(`Invalid ${fieldName} filter value: contains disallowed characters`);
7
- }
8
- return value.replace(/'/g, "''");
9
- }
10
- class LanceStore {
11
- db = null;
12
- table = null;
13
- dbPath;
14
- tableName;
15
- constructor(options) {
16
- this.dbPath = options?.path ?? STORE_DEFAULTS.path;
17
- this.tableName = options?.tableName ?? STORE_DEFAULTS.tableName;
18
- }
19
- async initialize() {
20
- this.db = await connect(this.dbPath);
21
- const tableNames = await this.db.tableNames();
22
- if (tableNames.includes(this.tableName)) {
23
- this.table = await this.db.openTable(this.tableName);
24
- await this.createFtsIndex();
25
- }
26
- }
27
- async upsert(records, vectors) {
28
- if (records.length === 0) return;
29
- if (records.length !== vectors.length) {
30
- throw new Error(
31
- `Record count (${records.length}) does not match vector count (${vectors.length})`
32
- );
33
- }
34
- const lanceRecords = records.map(
35
- (r, i) => ({
36
- id: r.id,
37
- vector: Array.from(vectors[i]),
38
- content: r.content,
39
- sourcePath: r.sourcePath,
40
- contentType: r.contentType,
41
- headingPath: r.headingPath ?? "",
42
- chunkIndex: r.chunkIndex,
43
- totalChunks: r.totalChunks,
44
- startLine: r.startLine,
45
- endLine: r.endLine,
46
- fileHash: r.fileHash,
47
- indexedAt: r.indexedAt,
48
- origin: r.origin,
49
- tags: JSON.stringify(r.tags),
50
- category: r.category ?? "",
51
- version: r.version
52
- })
53
- );
54
- if (!this.table) {
55
- try {
56
- this.table = await this.db?.createTable(this.tableName, lanceRecords) ?? null;
57
- } catch (err) {
58
- if (String(err).includes("already exists") && this.db) {
59
- this.table = await this.db.openTable(this.tableName);
60
- await this.table.add(lanceRecords);
61
- } else {
62
- throw err;
63
- }
64
- }
65
- } else {
66
- const sourcePaths = [...new Set(records.map((r) => r.sourcePath))];
67
- for (const sp of sourcePaths) {
68
- try {
69
- await this.table.delete(`sourcePath = '${sanitizeFilterValue(sp, "sourcePath")}'`);
70
- } catch {
71
- }
72
- }
73
- await this.table.add(lanceRecords);
74
- }
75
- }
76
- async search(queryVector, options) {
77
- if (!this.table) return [];
78
- const limit = options?.limit ?? SEARCH_DEFAULTS.maxResults;
79
- const minScore = options?.minScore ?? SEARCH_DEFAULTS.minScore;
80
- let query = this.table.search(queryVector).limit(limit * 2);
81
- const filterStr = this.buildFilterString(options);
82
- if (filterStr) {
83
- query = query.where(filterStr);
84
- }
85
- const results = await query.toArray();
86
- return results.map((row) => ({
87
- record: this.fromLanceRecord(row),
88
- score: 1 - (row._distance ?? 1)
89
- // LanceDB returns L2 distance; convert to similarity
90
- })).filter((r) => r.score >= minScore).slice(0, limit);
91
- }
92
- async createFtsIndex() {
93
- if (!this.table) return;
94
- try {
95
- await this.table.createIndex("content", { config: Index.fts() });
96
- console.error("[KB] FTS index created on content column");
97
- } catch (err) {
98
- if (!String(err).includes("already exists")) {
99
- console.error("[KB] FTS index creation failed (non-fatal):", err);
100
- }
101
- }
102
- }
103
- async ftsSearch(query, options) {
104
- if (!this.table) return [];
105
- const limit = options?.limit ?? SEARCH_DEFAULTS.maxResults;
106
- try {
107
- let searchQuery = this.table.search(query).limit(limit * 2);
108
- const filterStr = this.buildFilterString(options);
109
- if (filterStr) {
110
- searchQuery = searchQuery.where(filterStr);
111
- }
112
- const results = await searchQuery.toArray();
113
- return results.map((row) => ({
114
- record: this.fromLanceRecord(row),
115
- score: row._score ?? row._relevance_score ?? 0
116
- }));
117
- } catch (err) {
118
- console.error("[KB] FTS search failed (non-fatal):", err);
119
- return [];
120
- }
121
- }
122
- async getById(id) {
123
- if (!this.table) return null;
124
- const results = await this.table.query().where(`id = '${sanitizeFilterValue(id, "id")}'`).limit(1).toArray();
125
- if (results.length === 0) return null;
126
- return this.fromLanceRecord(results[0]);
127
- }
128
- async deleteBySourcePath(sourcePath) {
129
- if (!this.table) return 0;
130
- const existing = await this.getBySourcePath(sourcePath);
131
- if (existing.length === 0) return 0;
132
- await this.table.delete(`sourcePath = '${sanitizeFilterValue(sourcePath, "sourcePath")}'`);
133
- return existing.length;
134
- }
135
- async deleteById(id) {
136
- if (!this.table) return false;
137
- const existing = await this.getById(id);
138
- if (!existing) return false;
139
- await this.table.delete(`id = '${sanitizeFilterValue(id, "id")}'`);
140
- return true;
141
- }
142
- async getBySourcePath(sourcePath) {
143
- if (!this.table) return [];
144
- const results = await this.table.query().where(`sourcePath = '${sanitizeFilterValue(sourcePath, "sourcePath")}'`).limit(1e3).toArray();
145
- return results.map((row) => this.fromLanceRecord(row));
146
- }
147
- async getStats() {
148
- if (!this.table) {
149
- return {
150
- totalRecords: 0,
151
- totalFiles: 0,
152
- contentTypeBreakdown: {},
153
- lastIndexedAt: null,
154
- storeBackend: "lancedb",
155
- embeddingModel: EMBEDDING_DEFAULTS.model
156
- };
157
- }
158
- const allRows = await this.table.countRows();
159
- const sample = await this.table.query().select(["sourcePath", "contentType", "indexedAt"]).limit(1e5).toArray();
160
- const breakdown = {};
161
- const uniquePaths = /* @__PURE__ */ new Set();
162
- let lastIndexedAt = null;
163
- for (const row of sample) {
164
- const r = row;
165
- breakdown[r.contentType] = (breakdown[r.contentType] ?? 0) + 1;
166
- uniquePaths.add(r.sourcePath);
167
- if (!lastIndexedAt || r.indexedAt > lastIndexedAt) {
168
- lastIndexedAt = r.indexedAt;
169
- }
170
- }
171
- return {
172
- totalRecords: allRows,
173
- totalFiles: uniquePaths.size,
174
- contentTypeBreakdown: breakdown,
175
- lastIndexedAt,
176
- storeBackend: "lancedb",
177
- embeddingModel: EMBEDDING_DEFAULTS.model
178
- };
179
- }
180
- async listSourcePaths() {
181
- if (!this.table) return [];
182
- const results = await this.table.query().select(["sourcePath"]).limit(1e5).toArray();
183
- return [
184
- // biome-ignore lint/suspicious/noExplicitAny: LanceDB query returns untyped results
185
- ...new Set(results.map((r) => r.sourcePath))
186
- ];
187
- }
188
- async dropTable() {
189
- if (this.db) {
190
- const tableNames = await this.db.tableNames();
191
- if (tableNames.includes(this.tableName)) {
192
- const maxRetries = 3;
193
- for (let attempt = 1; attempt <= maxRetries; attempt++) {
194
- try {
195
- await this.db.dropTable(this.tableName);
196
- break;
197
- } catch (err) {
198
- if (attempt === maxRetries) throw err;
199
- const delay = attempt * 500;
200
- console.error(`[KB] dropTable attempt ${attempt} failed, retrying in ${delay}ms...`);
201
- await new Promise((r) => setTimeout(r, delay));
202
- }
203
- }
204
- }
205
- }
206
- this.table = null;
207
- }
208
- async close() {
209
- try {
210
- if (this.db && typeof this.db.close === "function") {
211
- await this.db.close();
212
- }
213
- } catch {
214
- }
215
- this.table = null;
216
- this.db = null;
217
- }
218
- buildFilterString(options) {
219
- const filters = [];
220
- if (options?.contentType) {
221
- filters.push(`contentType = '${sanitizeFilterValue(options.contentType, "contentType")}'`);
222
- }
223
- if (options?.origin) {
224
- filters.push(`origin = '${sanitizeFilterValue(options.origin, "origin")}'`);
225
- }
226
- if (options?.category) {
227
- filters.push(`category = '${sanitizeFilterValue(options.category, "category")}'`);
228
- }
229
- if (options?.tags && options.tags.length > 0) {
230
- const tagClauses = options.tags.map((t) => `tags LIKE '%${sanitizeFilterValue(t, "tag")}%'`);
231
- filters.push(`(${tagClauses.join(" OR ")})`);
232
- }
233
- return filters.length > 0 ? filters.join(" AND ") : null;
234
- }
235
- fromLanceRecord(row) {
236
- return {
237
- id: row.id,
238
- content: row.content,
239
- sourcePath: row.sourcePath,
240
- contentType: row.contentType,
241
- headingPath: row.headingPath || void 0,
242
- chunkIndex: row.chunkIndex,
243
- totalChunks: row.totalChunks,
244
- startLine: row.startLine,
245
- endLine: row.endLine,
246
- fileHash: row.fileHash,
247
- indexedAt: row.indexedAt,
248
- origin: row.origin,
249
- tags: JSON.parse(row.tags || "[]"),
250
- category: row.category || void 0,
251
- version: row.version
252
- };
253
- }
254
- }
255
- export {
256
- LanceStore
257
- };
258
- //# sourceMappingURL=lance-store.js.map
1
+ import{EMBEDDING_DEFAULTS as h,SEARCH_DEFAULTS as d,STORE_DEFAULTS as u}from"../../core/dist/index.js";import{connect as g,Index as m}from"@lancedb/lancedb";const b=/^[\w.\-/ ]+$/;function r(l,e){if(!b.test(l))throw new Error(`Invalid ${e} filter value: contains disallowed characters`);return l.replace(/'/g,"''")}class p{db=null;table=null;dbPath;tableName;constructor(e){this.dbPath=e?.path??u.path,this.tableName=e?.tableName??u.tableName}async initialize(){this.db=await g(this.dbPath),(await this.db.tableNames()).includes(this.tableName)&&(this.table=await this.db.openTable(this.tableName),await this.createFtsIndex())}async upsert(e,n){if(e.length===0)return;if(e.length!==n.length)throw new Error(`Record count (${e.length}) does not match vector count (${n.length})`);const a=e.map((t,i)=>({id:t.id,vector:Array.from(n[i]),content:t.content,sourcePath:t.sourcePath,contentType:t.contentType,headingPath:t.headingPath??"",chunkIndex:t.chunkIndex,totalChunks:t.totalChunks,startLine:t.startLine,endLine:t.endLine,fileHash:t.fileHash,indexedAt:t.indexedAt,origin:t.origin,tags:JSON.stringify(t.tags),category:t.category??"",version:t.version}));if(this.table){const t=[...new Set(e.map(i=>i.sourcePath))];for(const i of t)try{await this.table.delete(`sourcePath = '${r(i,"sourcePath")}'`)}catch{}await this.table.add(a)}else try{this.table=await this.db?.createTable(this.tableName,a)??null}catch(t){if(String(t).includes("already exists")&&this.db)this.table=await this.db.openTable(this.tableName),await this.table.add(a);else throw t}}async search(e,n){if(!this.table)return[];const a=n?.limit??d.maxResults,t=n?.minScore??d.minScore;let i=this.table.search(e).limit(a*2);const o=this.buildFilterString(n);return o&&(i=i.where(o)),(await i.toArray()).map(c=>({record:this.fromLanceRecord(c),score:1-(c._distance??1)})).filter(c=>c.score>=t).slice(0,a)}async createFtsIndex(){if(this.table)try{await this.table.createIndex("content",{config:m.fts()}),console.error("[KB] FTS index created on content column")}catch(e){String(e).includes("already exists")||console.error("[KB] FTS index creation failed (non-fatal):",e)}}async ftsSearch(e,n){if(!this.table)return[];const a=n?.limit??d.maxResults;try{let t=this.table.search(e).limit(a*2);const i=this.buildFilterString(n);return i&&(t=t.where(i)),(await t.toArray()).map(s=>({record:this.fromLanceRecord(s),score:s._score??s._relevance_score??0}))}catch(t){return console.error("[KB] FTS search failed (non-fatal):",t),[]}}async getById(e){if(!this.table)return null;const n=await this.table.query().where(`id = '${r(e,"id")}'`).limit(1).toArray();return n.length===0?null:this.fromLanceRecord(n[0])}async deleteBySourcePath(e){if(!this.table)return 0;const n=await this.getBySourcePath(e);return n.length===0?0:(await this.table.delete(`sourcePath = '${r(e,"sourcePath")}'`),n.length)}async deleteById(e){return!this.table||!await this.getById(e)?!1:(await this.table.delete(`id = '${r(e,"id")}'`),!0)}async getBySourcePath(e){return this.table?(await this.table.query().where(`sourcePath = '${r(e,"sourcePath")}'`).limit(1e3).toArray()).map(a=>this.fromLanceRecord(a)):[]}async getStats(){if(!this.table)return{totalRecords:0,totalFiles:0,contentTypeBreakdown:{},lastIndexedAt:null,storeBackend:"lancedb",embeddingModel:h.model};const e=await this.table.countRows(),n=await this.table.query().select(["sourcePath","contentType","indexedAt"]).limit(1e5).toArray(),a={},t=new Set;let i=null;for(const o of n){const s=o;a[s.contentType]=(a[s.contentType]??0)+1,t.add(s.sourcePath),(!i||s.indexedAt>i)&&(i=s.indexedAt)}return{totalRecords:e,totalFiles:t.size,contentTypeBreakdown:a,lastIndexedAt:i,storeBackend:"lancedb",embeddingModel:h.model}}async listSourcePaths(){if(!this.table)return[];const e=await this.table.query().select(["sourcePath"]).limit(1e5).toArray();return[...new Set(e.map(n=>n.sourcePath))]}async dropTable(){if(this.db&&(await this.db.tableNames()).includes(this.tableName))for(let a=1;a<=3;a++)try{await this.db.dropTable(this.tableName);break}catch(t){if(a===3)throw t;const i=a*500;console.error(`[KB] dropTable attempt ${a} failed, retrying in ${i}ms...`),await new Promise(o=>setTimeout(o,i))}this.table=null}async close(){try{this.db&&typeof this.db.close=="function"&&await this.db.close()}catch{}this.table=null,this.db=null}buildFilterString(e){const n=[];if(e?.contentType&&n.push(`contentType = '${r(e.contentType,"contentType")}'`),e?.origin&&n.push(`origin = '${r(e.origin,"origin")}'`),e?.category&&n.push(`category = '${r(e.category,"category")}'`),e?.tags&&e.tags.length>0){const a=e.tags.map(t=>`tags LIKE '%${r(t,"tag")}%'`);n.push(`(${a.join(" OR ")})`)}return n.length>0?n.join(" AND "):null}fromLanceRecord(e){return{id:e.id,content:e.content,sourcePath:e.sourcePath,contentType:e.contentType,headingPath:e.headingPath||void 0,chunkIndex:e.chunkIndex,totalChunks:e.totalChunks,startLine:e.startLine,endLine:e.endLine,fileHash:e.fileHash,indexedAt:e.indexedAt,origin:e.origin,tags:JSON.parse(e.tags||"[]"),category:e.category||void 0,version:e.version}}}export{p as LanceStore};
@@ -1,22 +1,4 @@
1
- import { existsSync, mkdirSync } from "node:fs";
2
- import { dirname, join } from "node:path";
3
- class SqliteGraphStore {
4
- db = null;
5
- dbPath;
6
- constructor(options) {
7
- const basePath = options?.path ?? ".kb-data";
8
- this.dbPath = join(basePath, "graph.db");
9
- }
10
- async initialize() {
11
- const dir = dirname(this.dbPath);
12
- if (!existsSync(dir)) {
13
- mkdirSync(dir, { recursive: true });
14
- }
15
- const BetterSqlite3 = (await import("better-sqlite3")).default;
16
- this.db = new BetterSqlite3(this.dbPath);
17
- this.db.pragma("journal_mode = WAL");
18
- this.db.pragma("foreign_keys = ON");
19
- this.db.exec(`
1
+ import{existsSync as l,mkdirSync as N}from"node:fs";import{dirname as y,join as S}from"node:path";class f{db=null;dbPath;constructor(e){const t=e?.path??".kb-data";this.dbPath=S(t,"graph.db")}async initialize(){const e=y(this.dbPath);l(e)||N(e,{recursive:!0});const t=(await import("better-sqlite3")).default;this.db=new t(this.dbPath),this.db.pragma("journal_mode = WAL"),this.db.pragma("foreign_keys = ON"),this.db.exec(`
20
2
  CREATE TABLE IF NOT EXISTS nodes (
21
3
  id TEXT PRIMARY KEY,
22
4
  type TEXT NOT NULL,
@@ -44,15 +26,7 @@ class SqliteGraphStore {
44
26
  CREATE INDEX IF NOT EXISTS idx_edges_from ON edges(from_id);
45
27
  CREATE INDEX IF NOT EXISTS idx_edges_to ON edges(to_id);
46
28
  CREATE INDEX IF NOT EXISTS idx_edges_type ON edges(type);
47
- `);
48
- }
49
- ensureDb() {
50
- if (!this.db) throw new Error("Graph store not initialized \u2014 call initialize() first");
51
- return this.db;
52
- }
53
- async upsertNode(node) {
54
- const db = this.ensureDb();
55
- db.prepare(`
29
+ `)}ensureDb(){if(!this.db)throw new Error("Graph store not initialized \u2014 call initialize() first");return this.db}async upsertNode(e){this.ensureDb().prepare(`
56
30
  INSERT INTO nodes (id, type, name, properties, source_record_id, source_path, created_at)
57
31
  VALUES (?, ?, ?, ?, ?, ?, ?)
58
32
  ON CONFLICT(id) DO UPDATE SET
@@ -61,19 +35,7 @@ class SqliteGraphStore {
61
35
  properties = excluded.properties,
62
36
  source_record_id = excluded.source_record_id,
63
37
  source_path = excluded.source_path
64
- `).run(
65
- node.id,
66
- node.type,
67
- node.name,
68
- JSON.stringify(node.properties),
69
- node.sourceRecordId ?? null,
70
- node.sourcePath ?? null,
71
- node.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
72
- );
73
- }
74
- async upsertEdge(edge) {
75
- const db = this.ensureDb();
76
- db.prepare(`
38
+ `).run(e.id,e.type,e.name,JSON.stringify(e.properties),e.sourceRecordId??null,e.sourcePath??null,e.createdAt??new Date().toISOString())}async upsertEdge(e){this.ensureDb().prepare(`
77
39
  INSERT INTO edges (id, from_id, to_id, type, weight, properties)
78
40
  VALUES (?, ?, ?, ?, ?, ?)
79
41
  ON CONFLICT(id) DO UPDATE SET
@@ -82,19 +44,7 @@ class SqliteGraphStore {
82
44
  type = excluded.type,
83
45
  weight = excluded.weight,
84
46
  properties = excluded.properties
85
- `).run(
86
- edge.id,
87
- edge.fromId,
88
- edge.toId,
89
- edge.type,
90
- edge.weight ?? 1,
91
- JSON.stringify(edge.properties ?? {})
92
- );
93
- }
94
- async upsertNodes(nodes) {
95
- if (nodes.length === 0) return;
96
- const db = this.ensureDb();
97
- const stmt = db.prepare(`
47
+ `).run(e.id,e.fromId,e.toId,e.type,e.weight??1,JSON.stringify(e.properties??{}))}async upsertNodes(e){if(e.length===0)return;const t=this.ensureDb(),s=t.prepare(`
98
48
  INSERT INTO nodes (id, type, name, properties, source_record_id, source_path, created_at)
99
49
  VALUES (?, ?, ?, ?, ?, ?, ?)
100
50
  ON CONFLICT(id) DO UPDATE SET
@@ -103,26 +53,7 @@ class SqliteGraphStore {
103
53
  properties = excluded.properties,
104
54
  source_record_id = excluded.source_record_id,
105
55
  source_path = excluded.source_path
106
- `);
107
- const tx = db.transaction(() => {
108
- for (const node of nodes) {
109
- stmt.run(
110
- node.id,
111
- node.type,
112
- node.name,
113
- JSON.stringify(node.properties),
114
- node.sourceRecordId ?? null,
115
- node.sourcePath ?? null,
116
- node.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
117
- );
118
- }
119
- });
120
- tx();
121
- }
122
- async upsertEdges(edges) {
123
- if (edges.length === 0) return;
124
- const db = this.ensureDb();
125
- const stmt = db.prepare(`
56
+ `);t.transaction(()=>{for(const r of e)s.run(r.id,r.type,r.name,JSON.stringify(r.properties),r.sourceRecordId??null,r.sourcePath??null,r.createdAt??new Date().toISOString())})()}async upsertEdges(e){if(e.length===0)return;const t=this.ensureDb(),s=t.prepare(`
126
57
  INSERT INTO edges (id, from_id, to_id, type, weight, properties)
127
58
  VALUES (?, ?, ?, ?, ?, ?)
128
59
  ON CONFLICT(id) DO UPDATE SET
@@ -131,244 +62,12 @@ class SqliteGraphStore {
131
62
  type = excluded.type,
132
63
  weight = excluded.weight,
133
64
  properties = excluded.properties
134
- `);
135
- const tx = db.transaction(() => {
136
- for (const edge of edges) {
137
- stmt.run(
138
- edge.id,
139
- edge.fromId,
140
- edge.toId,
141
- edge.type,
142
- edge.weight ?? 1,
143
- JSON.stringify(edge.properties ?? {})
144
- );
145
- }
146
- });
147
- tx();
148
- }
149
- async getNode(id) {
150
- const db = this.ensureDb();
151
- const row = db.prepare("SELECT * FROM nodes WHERE id = ?").get(id);
152
- return row ? this.toGraphNode(row) : null;
153
- }
154
- async getNeighbors(nodeId, options) {
155
- const db = this.ensureDb();
156
- const direction = options?.direction ?? "both";
157
- const edgeType = options?.edgeType;
158
- const limit = options?.limit ?? 50;
159
- const nodes = [];
160
- const edges = [];
161
- const seenNodeIds = /* @__PURE__ */ new Set();
162
- const OUTGOING_SQL = `
65
+ `);t.transaction(()=>{for(const r of e)s.run(r.id,r.fromId,r.toId,r.type,r.weight??1,JSON.stringify(r.properties??{}))})()}async getNode(e){const s=this.ensureDb().prepare("SELECT * FROM nodes WHERE id = ?").get(e);return s?this.toGraphNode(s):null}async getNeighbors(e,t){const s=this.ensureDb(),o=t?.direction??"both",r=t?.edgeType,a=t?.limit??50,p=[],d=[],E=new Set,_=`
163
66
  SELECT e.id AS edge_id, e.from_id, e.to_id, e.type AS edge_type, e.weight, e.properties AS edge_props,
164
67
  n.id AS node_id, n.type AS node_type, n.name AS node_name, n.properties AS node_props,
165
68
  n.source_record_id AS node_src_rec, n.source_path AS node_src_path, n.created_at AS node_created
166
- FROM edges e JOIN nodes n ON e.to_id = n.id WHERE e.from_id = ?`;
167
- const INCOMING_SQL = `
69
+ FROM edges e JOIN nodes n ON e.to_id = n.id WHERE e.from_id = ?`,u=`
168
70
  SELECT e.id AS edge_id, e.from_id, e.to_id, e.type AS edge_type, e.weight, e.properties AS edge_props,
169
71
  n.id AS node_id, n.type AS node_type, n.name AS node_name, n.properties AS node_props,
170
72
  n.source_record_id AS node_src_rec, n.source_path AS node_src_path, n.created_at AS node_created
171
- FROM edges e JOIN nodes n ON e.from_id = n.id WHERE e.to_id = ?`;
172
- if (direction === "outgoing" || direction === "both") {
173
- let sql = OUTGOING_SQL;
174
- const params = [nodeId];
175
- if (edgeType) {
176
- sql += " AND e.type = ?";
177
- params.push(edgeType);
178
- }
179
- sql += " LIMIT ?";
180
- params.push(limit);
181
- const rows = db.prepare(sql).all(...params);
182
- for (const row of rows) {
183
- edges.push(joinRowToEdge(row));
184
- if (!seenNodeIds.has(row.node_id)) {
185
- seenNodeIds.add(row.node_id);
186
- nodes.push(joinRowToNode(row));
187
- }
188
- }
189
- }
190
- if (direction === "incoming" || direction === "both") {
191
- let sql = INCOMING_SQL;
192
- const params = [nodeId];
193
- if (edgeType) {
194
- sql += " AND e.type = ?";
195
- params.push(edgeType);
196
- }
197
- sql += " LIMIT ?";
198
- params.push(limit);
199
- const rows = db.prepare(sql).all(...params);
200
- for (const row of rows) {
201
- edges.push(joinRowToEdge(row));
202
- if (!seenNodeIds.has(row.node_id)) {
203
- seenNodeIds.add(row.node_id);
204
- nodes.push(joinRowToNode(row));
205
- }
206
- }
207
- }
208
- return { nodes, edges };
209
- }
210
- async traverse(startId, options) {
211
- const maxDepth = options?.maxDepth ?? 2;
212
- const direction = options?.direction ?? "both";
213
- const edgeType = options?.edgeType;
214
- const limit = options?.limit ?? 50;
215
- const allNodes = /* @__PURE__ */ new Map();
216
- const allEdges = /* @__PURE__ */ new Map();
217
- const visited = /* @__PURE__ */ new Set();
218
- const queue = [{ nodeId: startId, depth: 0 }];
219
- while (queue.length > 0 && allNodes.size < limit) {
220
- const current = queue.shift();
221
- if (!current || visited.has(current.nodeId)) continue;
222
- if (current.depth > maxDepth) continue;
223
- visited.add(current.nodeId);
224
- const neighbors = await this.getNeighbors(current.nodeId, {
225
- direction,
226
- edgeType,
227
- limit: limit - allNodes.size
228
- });
229
- for (const node of neighbors.nodes) {
230
- if (!allNodes.has(node.id)) {
231
- allNodes.set(node.id, node);
232
- if (current.depth + 1 < maxDepth) {
233
- queue.push({ nodeId: node.id, depth: current.depth + 1 });
234
- }
235
- }
236
- }
237
- for (const edge of neighbors.edges) {
238
- allEdges.set(edge.id, edge);
239
- }
240
- }
241
- return { nodes: [...allNodes.values()], edges: [...allEdges.values()] };
242
- }
243
- async findNodes(filter) {
244
- const db = this.ensureDb();
245
- const conditions = [];
246
- const params = [];
247
- if (filter.type) {
248
- conditions.push("type = ?");
249
- params.push(filter.type);
250
- }
251
- if (filter.namePattern) {
252
- conditions.push("name LIKE ?");
253
- params.push(`%${filter.namePattern}%`);
254
- }
255
- if (filter.sourcePath) {
256
- conditions.push("source_path = ?");
257
- params.push(filter.sourcePath);
258
- }
259
- const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
260
- const maxRows = filter.limit ?? 100;
261
- const rows = db.prepare(`SELECT * FROM nodes ${where} LIMIT ?`).all(...params, maxRows);
262
- return rows.map((r) => this.toGraphNode(r));
263
- }
264
- async findEdges(filter) {
265
- const db = this.ensureDb();
266
- const conditions = [];
267
- const params = [];
268
- if (filter.type) {
269
- conditions.push("type = ?");
270
- params.push(filter.type);
271
- }
272
- if (filter.fromId) {
273
- conditions.push("from_id = ?");
274
- params.push(filter.fromId);
275
- }
276
- if (filter.toId) {
277
- conditions.push("to_id = ?");
278
- params.push(filter.toId);
279
- }
280
- const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
281
- const maxRows = filter.limit ?? 100;
282
- const rows = db.prepare(`SELECT * FROM edges ${where} LIMIT ?`).all(...params, maxRows);
283
- return rows.map((r) => this.toGraphEdge(r));
284
- }
285
- async deleteNode(id) {
286
- const db = this.ensureDb();
287
- db.transaction(() => {
288
- db.prepare("DELETE FROM edges WHERE from_id = ? OR to_id = ?").run(id, id);
289
- db.prepare("DELETE FROM nodes WHERE id = ?").run(id);
290
- })();
291
- }
292
- async deleteBySourcePath(sourcePath) {
293
- const db = this.ensureDb();
294
- const nodeIds = db.prepare("SELECT id FROM nodes WHERE source_path = ?").all(sourcePath);
295
- if (nodeIds.length === 0) return 0;
296
- const tx = db.transaction(() => {
297
- for (const { id } of nodeIds) {
298
- db.prepare("DELETE FROM edges WHERE from_id = ? OR to_id = ?").run(id, id);
299
- }
300
- db.prepare("DELETE FROM nodes WHERE source_path = ?").run(sourcePath);
301
- });
302
- tx();
303
- return nodeIds.length;
304
- }
305
- async clear() {
306
- const db = this.ensureDb();
307
- db.exec("DELETE FROM edges; DELETE FROM nodes;");
308
- }
309
- async getStats() {
310
- const db = this.ensureDb();
311
- const nodeCount = db.prepare("SELECT COUNT(*) as count FROM nodes").get().count;
312
- const edgeCount = db.prepare("SELECT COUNT(*) as count FROM edges").get().count;
313
- const nodeTypeRows = db.prepare("SELECT type, COUNT(*) as count FROM nodes GROUP BY type").all();
314
- const nodeTypes = {};
315
- for (const row of nodeTypeRows) nodeTypes[row.type] = row.count;
316
- const edgeTypeRows = db.prepare("SELECT type, COUNT(*) as count FROM edges GROUP BY type").all();
317
- const edgeTypes = {};
318
- for (const row of edgeTypeRows) edgeTypes[row.type] = row.count;
319
- return { nodeCount, edgeCount, nodeTypes, edgeTypes };
320
- }
321
- async close() {
322
- if (this.db) {
323
- this.db.close();
324
- this.db = null;
325
- }
326
- }
327
- // ── Private helpers ─────────────────────────────────────────────────
328
- toGraphNode(row) {
329
- return {
330
- id: row.id,
331
- type: row.type,
332
- name: row.name,
333
- properties: JSON.parse(row.properties),
334
- sourceRecordId: row.source_record_id ?? void 0,
335
- sourcePath: row.source_path ?? void 0,
336
- createdAt: row.created_at
337
- };
338
- }
339
- toGraphEdge(row) {
340
- return {
341
- id: row.id,
342
- fromId: row.from_id,
343
- toId: row.to_id,
344
- type: row.type,
345
- weight: row.weight ?? 1,
346
- properties: JSON.parse(row.properties)
347
- };
348
- }
349
- }
350
- function joinRowToEdge(row) {
351
- return {
352
- id: row.edge_id,
353
- fromId: row.from_id,
354
- toId: row.to_id,
355
- type: row.edge_type,
356
- weight: row.weight ?? 1,
357
- properties: JSON.parse(row.edge_props ?? "{}")
358
- };
359
- }
360
- function joinRowToNode(row) {
361
- return {
362
- id: row.node_id,
363
- type: row.node_type,
364
- name: row.node_name,
365
- properties: JSON.parse(row.node_props ?? "{}"),
366
- sourceRecordId: row.node_src_rec ?? void 0,
367
- sourcePath: row.node_src_path ?? void 0,
368
- createdAt: row.node_created
369
- };
370
- }
371
- export {
372
- SqliteGraphStore
373
- };
374
- //# sourceMappingURL=sqlite-graph-store.js.map
73
+ FROM edges e JOIN nodes n ON e.from_id = n.id WHERE e.to_id = ?`;if(o==="outgoing"||o==="both"){let c=_;const i=[e];r&&(c+=" AND e.type = ?",i.push(r)),c+=" LIMIT ?",i.push(a);const g=s.prepare(c).all(...i);for(const h of g)d.push(T(h)),E.has(h.node_id)||(E.add(h.node_id),p.push(m(h)))}if(o==="incoming"||o==="both"){let c=u;const i=[e];r&&(c+=" AND e.type = ?",i.push(r)),c+=" LIMIT ?",i.push(a);const g=s.prepare(c).all(...i);for(const h of g)d.push(T(h)),E.has(h.node_id)||(E.add(h.node_id),p.push(m(h)))}return{nodes:p,edges:d}}async traverse(e,t){const s=t?.maxDepth??2,o=t?.direction??"both",r=t?.edgeType,a=t?.limit??50,p=new Map,d=new Map,E=new Set,_=[{nodeId:e,depth:0}];for(;_.length>0&&p.size<a;){const u=_.shift();if(!u||E.has(u.nodeId)||u.depth>s)continue;E.add(u.nodeId);const c=await this.getNeighbors(u.nodeId,{direction:o,edgeType:r,limit:a-p.size});for(const i of c.nodes)p.has(i.id)||(p.set(i.id,i),u.depth+1<s&&_.push({nodeId:i.id,depth:u.depth+1}));for(const i of c.edges)d.set(i.id,i)}return{nodes:[...p.values()],edges:[...d.values()]}}async findNodes(e){const t=this.ensureDb(),s=[],o=[];e.type&&(s.push("type = ?"),o.push(e.type)),e.namePattern&&(s.push("name LIKE ?"),o.push(`%${e.namePattern}%`)),e.sourcePath&&(s.push("source_path = ?"),o.push(e.sourcePath));const r=s.length>0?`WHERE ${s.join(" AND ")}`:"",a=e.limit??100;return t.prepare(`SELECT * FROM nodes ${r} LIMIT ?`).all(...o,a).map(d=>this.toGraphNode(d))}async findEdges(e){const t=this.ensureDb(),s=[],o=[];e.type&&(s.push("type = ?"),o.push(e.type)),e.fromId&&(s.push("from_id = ?"),o.push(e.fromId)),e.toId&&(s.push("to_id = ?"),o.push(e.toId));const r=s.length>0?`WHERE ${s.join(" AND ")}`:"",a=e.limit??100;return t.prepare(`SELECT * FROM edges ${r} LIMIT ?`).all(...o,a).map(d=>this.toGraphEdge(d))}async deleteNode(e){const t=this.ensureDb();t.transaction(()=>{t.prepare("DELETE FROM edges WHERE from_id = ? OR to_id = ?").run(e,e),t.prepare("DELETE FROM nodes WHERE id = ?").run(e)})()}async deleteBySourcePath(e){const t=this.ensureDb(),s=t.prepare("SELECT id FROM nodes WHERE source_path = ?").all(e);return s.length===0?0:(t.transaction(()=>{for(const{id:r}of s)t.prepare("DELETE FROM edges WHERE from_id = ? OR to_id = ?").run(r,r);t.prepare("DELETE FROM nodes WHERE source_path = ?").run(e)})(),s.length)}async clear(){this.ensureDb().exec("DELETE FROM edges; DELETE FROM nodes;")}async getStats(){const e=this.ensureDb(),t=e.prepare("SELECT COUNT(*) as count FROM nodes").get().count,s=e.prepare("SELECT COUNT(*) as count FROM edges").get().count,o=e.prepare("SELECT type, COUNT(*) as count FROM nodes GROUP BY type").all(),r={};for(const d of o)r[d.type]=d.count;const a=e.prepare("SELECT type, COUNT(*) as count FROM edges GROUP BY type").all(),p={};for(const d of a)p[d.type]=d.count;return{nodeCount:t,edgeCount:s,nodeTypes:r,edgeTypes:p}}async close(){this.db&&(this.db.close(),this.db=null)}toGraphNode(e){return{id:e.id,type:e.type,name:e.name,properties:JSON.parse(e.properties),sourceRecordId:e.source_record_id??void 0,sourcePath:e.source_path??void 0,createdAt:e.created_at}}toGraphEdge(e){return{id:e.id,fromId:e.from_id,toId:e.to_id,type:e.type,weight:e.weight??1,properties:JSON.parse(e.properties)}}}function T(n){return{id:n.edge_id,fromId:n.from_id,toId:n.to_id,type:n.edge_type,weight:n.weight??1,properties:JSON.parse(n.edge_props??"{}")}}function m(n){return{id:n.node_id,type:n.node_type,name:n.node_name,properties:JSON.parse(n.node_props??"{}"),sourceRecordId:n.node_src_rec??void 0,sourcePath:n.node_src_path??void 0,createdAt:n.node_created}}export{f as SqliteGraphStore};
@@ -1,14 +1 @@
1
- async function createStore(config) {
2
- switch (config.backend) {
3
- case "lancedb": {
4
- const { LanceStore } = await import("./lance-store.js");
5
- return new LanceStore({ path: config.path });
6
- }
7
- default:
8
- throw new Error(`Unknown store backend: "${config.backend}". Supported: lancedb`);
9
- }
10
- }
11
- export {
12
- createStore
13
- };
14
- //# sourceMappingURL=store-factory.js.map
1
+ async function n(e){if(e.backend==="lancedb"){const{LanceStore:t}=await import("./lance-store.js");return new t({path:e.path})}else throw new Error(`Unknown store backend: "${e.backend}". Supported: lancedb`)}export{n as createStore};
@@ -1 +0,0 @@
1
- //# sourceMappingURL=store.interface.js.map