ruvnet-kb-first 6.4.0 → 6.5.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.
@@ -0,0 +1,238 @@
1
+ /**
2
+ * WASM KB Loader - Auto-generated
3
+ *
4
+ * Loads the embedded knowledge base into RvLite WASM.
5
+ * Provides semantic search with ~5ms latency.
6
+ *
7
+ * Content Hash: 62117666416c8c6e
8
+ * Generated: 2026-01-02T18:51:15.858Z
9
+ * Entries: 17,524
10
+ */
11
+
12
+ import fs from 'fs';
13
+ import path from 'path';
14
+ import { fileURLToPath, pathToFileURL } from 'url';
15
+
16
+ // Initialize WASM on first import
17
+ let wasmInitialized = false;
18
+ let RvLite, Embedder;
19
+
20
+ async function ensureWasmInit() {
21
+ if (!wasmInitialized) {
22
+ // Dynamic import to get the init function
23
+ const rvliteModule = await import('@ruvector/edge-full/rvlite');
24
+
25
+ // Get the wasm file path
26
+ const rvlitePath = path.dirname(fileURLToPath(import.meta.resolve('@ruvector/edge-full/rvlite')));
27
+ const wasmPath = path.join(rvlitePath, 'rvlite_bg.wasm');
28
+
29
+ // Read the wasm file and pass as buffer (Node.js compatible)
30
+ const wasmBuffer = fs.readFileSync(wasmPath);
31
+
32
+ // Initialize with the buffer
33
+ await rvliteModule.default(wasmBuffer);
34
+
35
+ // Get exports
36
+ RvLite = rvliteModule.RvLite;
37
+ Embedder = rvliteModule.Embedder;
38
+
39
+ wasmInitialized = true;
40
+ }
41
+ }
42
+
43
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
44
+
45
+ // KB Version Info
46
+ export const KB_VERSION = {
47
+ hash: '62117666416c8c6e',
48
+ exportedAt: '2026-01-02T18:51:15.858Z',
49
+ totalEntries: 17524,
50
+ embeddingDim: 384,
51
+ quantization: 'binary',
52
+ };
53
+
54
+ // Singleton instance
55
+ let db = null;
56
+ let embedder = null;
57
+ let entries = null;
58
+ let isLoaded = false;
59
+
60
+ /**
61
+ * Check if a newer KB version is available from PostgreSQL
62
+ */
63
+ export async function checkForUpdates(pgConfig) {
64
+ try {
65
+ const pg = await import('pg');
66
+ const client = new pg.default.Client(pgConfig || {
67
+ host: 'localhost',
68
+ port: 5435,
69
+ database: 'postgres',
70
+ user: 'postgres',
71
+ password: 'guruKB2025',
72
+ });
73
+
74
+ await client.connect();
75
+
76
+ // Get current hash from PostgreSQL
77
+ const result = await client.query(`
78
+ SELECT MD5(STRING_AGG(id::text || ':' || title || ':' || category, '|' ORDER BY id))::text as hash
79
+ FROM ask_ruvnet.architecture_docs
80
+ WHERE embedding IS NOT NULL AND is_duplicate = false
81
+ `);
82
+
83
+ await client.end();
84
+
85
+ const currentHash = result.rows[0]?.hash?.substring(0, 16) || 'unknown';
86
+ const needsUpdate = currentHash !== KB_VERSION.hash;
87
+
88
+ return {
89
+ embeddedHash: KB_VERSION.hash,
90
+ currentHash: currentHash,
91
+ needsUpdate: needsUpdate,
92
+ message: needsUpdate
93
+ ? 'KB has been updated. Run: npm update ruvnet-kb-first'
94
+ : 'KB is up to date',
95
+ };
96
+ } catch (e) {
97
+ return {
98
+ embeddedHash: KB_VERSION.hash,
99
+ currentHash: 'unavailable',
100
+ needsUpdate: false,
101
+ message: 'Could not check for updates (PostgreSQL not available)',
102
+ };
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Load the embedded KB into RvLite WASM
108
+ */
109
+ export async function loadKB() {
110
+ if (isLoaded) return { db, embedder, entries };
111
+
112
+ // Initialize WASM first
113
+ await ensureWasmInit();
114
+
115
+ console.log('Loading embedded KB...');
116
+ const startTime = Date.now();
117
+
118
+ // Load metadata
119
+ const metadataPath = path.join(__dirname, 'kb-metadata.json');
120
+ const metadata = JSON.parse(fs.readFileSync(metadataPath, 'utf-8'));
121
+
122
+ // Load entries
123
+ const entriesPath = path.join(__dirname, 'kb-entries.json');
124
+ entries = JSON.parse(fs.readFileSync(entriesPath, 'utf-8'));
125
+
126
+ // Load embeddings
127
+ const embeddingsPath = path.join(__dirname, 'kb-embeddings.bin');
128
+ const embeddingsBuffer = fs.readFileSync(embeddingsPath);
129
+
130
+ // Initialize RvLite with default config (384 dimensions, cosine)
131
+ db = RvLite.default();
132
+
133
+ // Initialize embedder for query embedding
134
+ embedder = new Embedder();
135
+
136
+ // Load vectors into RvLite
137
+ const bytesPerVector = metadata.quantization === 'binary'
138
+ ? Math.ceil(metadata.embeddingDim / 8)
139
+ : metadata.embeddingDim * 4;
140
+
141
+ for (let i = 0; i < entries.length; i++) {
142
+ const entry = entries[i];
143
+ const offset = i * bytesPerVector;
144
+
145
+ // For binary quantization, we need to convert back to float32 for RvLite
146
+ // This is a lightweight operation since we're just expanding bits
147
+ let vector;
148
+ if (metadata.quantization === 'binary') {
149
+ const binaryBytes = embeddingsBuffer.slice(offset, offset + bytesPerVector);
150
+ vector = new Float32Array(metadata.embeddingDim);
151
+ for (let j = 0; j < metadata.embeddingDim; j++) {
152
+ const byteIdx = Math.floor(j / 8);
153
+ const bitIdx = 7 - (j % 8);
154
+ vector[j] = (binaryBytes[byteIdx] & (1 << bitIdx)) ? 1.0 : -1.0;
155
+ }
156
+ } else {
157
+ vector = new Float32Array(embeddingsBuffer.buffer, offset, metadata.embeddingDim);
158
+ }
159
+
160
+ // Insert with metadata
161
+ db.insert_with_id(entry.id.toString(), vector, {
162
+ title: entry.title,
163
+ category: entry.category,
164
+ quality: entry.quality,
165
+ });
166
+ }
167
+
168
+ isLoaded = true;
169
+ const loadTime = Date.now() - startTime;
170
+ console.log(`KB loaded: ${entries.length.toLocaleString()} entries in ${loadTime}ms`);
171
+
172
+ return { db, embedder, entries };
173
+ }
174
+
175
+ /**
176
+ * Semantic search using embedded KB
177
+ */
178
+ export async function search(query, limit = 10, filter = null) {
179
+ await ensureWasmInit();
180
+ if (!isLoaded) await loadKB();
181
+
182
+ const startTime = Date.now();
183
+
184
+ // Generate query embedding
185
+ const queryVector = embedder.embed(query);
186
+
187
+ // Search
188
+ let results;
189
+ if (filter) {
190
+ results = db.search_with_filter(queryVector, limit, filter);
191
+ } else {
192
+ results = db.search(queryVector, limit);
193
+ }
194
+
195
+ // Enrich results with entry data
196
+ const enrichedResults = results.map(r => {
197
+ const entry = entries.find(e => e.id.toString() === r.id.toString());
198
+ return {
199
+ id: r.id,
200
+ score: r.score,
201
+ distance: 1 - r.score, // Convert similarity score to distance
202
+ title: entry?.title || 'Unknown',
203
+ content: entry?.content || '',
204
+ category: entry?.category || 'general',
205
+ quality: entry?.quality || 0,
206
+ };
207
+ });
208
+
209
+ const searchTime = Date.now() - startTime;
210
+
211
+ return {
212
+ results: enrichedResults,
213
+ searchTimeMs: searchTime,
214
+ query: query,
215
+ totalEntries: entries.length,
216
+ };
217
+ }
218
+
219
+ /**
220
+ * Get KB statistics
221
+ */
222
+ export function getStats() {
223
+ return {
224
+ version: KB_VERSION,
225
+ loaded: isLoaded,
226
+ entries: entries?.length || 0,
227
+ categories: KB_VERSION.totalEntries > 0 ? 15 : 0,
228
+ };
229
+ }
230
+
231
+ // Export for CommonJS compatibility
232
+ export default {
233
+ loadKB,
234
+ search,
235
+ checkForUpdates,
236
+ getStats,
237
+ KB_VERSION,
238
+ };
@@ -0,0 +1,71 @@
1
+ {
2
+ "version": "1.0.0",
3
+ "schema": "ask_ruvnet",
4
+ "exportedAt": "2026-01-02T18:51:15.858Z",
5
+ "totalEntries": 17524,
6
+ "embeddingDim": 384,
7
+ "quantization": "binary",
8
+ "categories": [
9
+ {
10
+ "name": "general",
11
+ "count": 9042
12
+ },
13
+ {
14
+ "name": "agents",
15
+ "count": 4628
16
+ },
17
+ {
18
+ "name": "vector-db",
19
+ "count": 885
20
+ },
21
+ {
22
+ "name": "swarms",
23
+ "count": 762
24
+ },
25
+ {
26
+ "name": "neural",
27
+ "count": 416
28
+ },
29
+ {
30
+ "name": "mcp",
31
+ "count": 296
32
+ },
33
+ {
34
+ "name": "memory",
35
+ "count": 273
36
+ },
37
+ {
38
+ "name": "deployment",
39
+ "count": 270
40
+ },
41
+ {
42
+ "name": "github",
43
+ "count": 256
44
+ },
45
+ {
46
+ "name": "sparc",
47
+ "count": 237
48
+ },
49
+ {
50
+ "name": "performance",
51
+ "count": 201
52
+ },
53
+ {
54
+ "name": "security",
55
+ "count": 139
56
+ },
57
+ {
58
+ "name": "reinforcement-learning",
59
+ "count": 81
60
+ },
61
+ {
62
+ "name": "llm",
63
+ "count": 24
64
+ },
65
+ {
66
+ "name": "consensus",
67
+ "count": 14
68
+ }
69
+ ],
70
+ "contentHash": "62117666416c8c6e"
71
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ruvnet-kb-first",
3
- "version": "6.4.0",
3
+ "version": "6.5.1",
4
4
  "description": "RuvNet KB-First Application Builder - Build intelligent applications on expert knowledge",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -48,6 +48,7 @@
48
48
  "url": "https://github.com/ruvnet/kb-first-builder/issues"
49
49
  },
50
50
  "dependencies": {
51
+ "@ruvector/edge-full": "^0.1.0",
51
52
  "agentic-flow": "^2.0.1-alpha.43",
52
53
  "chalk": "^5.3.0",
53
54
  "claude-flow": "^2.7.47",
@@ -81,6 +82,7 @@
81
82
  "templates/",
82
83
  "scripts/",
83
84
  "install/",
85
+ "kb-data/",
84
86
  "README.md",
85
87
  "SKILL.md"
86
88
  ]