@sylphx/flow 1.1.0 → 1.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 (45) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/package.json +12 -2
  3. package/src/commands/hook-command.ts +10 -230
  4. package/src/composables/index.ts +0 -1
  5. package/src/config/servers.ts +35 -78
  6. package/src/core/interfaces.ts +0 -33
  7. package/src/domains/index.ts +0 -2
  8. package/src/index.ts +0 -4
  9. package/src/services/mcp-service.ts +0 -16
  10. package/src/targets/claude-code.ts +3 -9
  11. package/src/targets/functional/claude-code-logic.ts +4 -22
  12. package/src/targets/opencode.ts +0 -6
  13. package/src/types/mcp.types.ts +29 -38
  14. package/src/types/target.types.ts +0 -2
  15. package/src/types.ts +0 -1
  16. package/src/commands/codebase-command.ts +0 -168
  17. package/src/commands/knowledge-command.ts +0 -161
  18. package/src/composables/useTargetConfig.ts +0 -45
  19. package/src/core/formatting/bytes.test.ts +0 -115
  20. package/src/core/validation/limit.test.ts +0 -155
  21. package/src/core/validation/query.test.ts +0 -44
  22. package/src/domains/codebase/index.ts +0 -5
  23. package/src/domains/codebase/tools.ts +0 -139
  24. package/src/domains/knowledge/index.ts +0 -10
  25. package/src/domains/knowledge/resources.ts +0 -537
  26. package/src/domains/knowledge/tools.ts +0 -174
  27. package/src/services/search/base-indexer.ts +0 -156
  28. package/src/services/search/codebase-indexer-types.ts +0 -38
  29. package/src/services/search/codebase-indexer.ts +0 -647
  30. package/src/services/search/embeddings-provider.ts +0 -455
  31. package/src/services/search/embeddings.ts +0 -316
  32. package/src/services/search/functional-indexer.ts +0 -323
  33. package/src/services/search/index.ts +0 -27
  34. package/src/services/search/indexer.ts +0 -380
  35. package/src/services/search/knowledge-indexer.ts +0 -422
  36. package/src/services/search/semantic-search.ts +0 -244
  37. package/src/services/search/tfidf.ts +0 -559
  38. package/src/services/search/unified-search-service.ts +0 -888
  39. package/src/services/storage/cache-storage.ts +0 -487
  40. package/src/services/storage/drizzle-storage.ts +0 -581
  41. package/src/services/storage/index.ts +0 -15
  42. package/src/services/storage/lancedb-vector-storage.ts +0 -494
  43. package/src/services/storage/memory-storage.ts +0 -268
  44. package/src/services/storage/separated-storage.ts +0 -467
  45. package/src/services/storage/vector-storage.ts +0 -13
@@ -1,494 +0,0 @@
1
- /**
2
- * Simple LanceDB vector storage implementation
3
- * Local-only, no cloud services required
4
- */
5
-
6
- import { logger } from '../../utils/logger.js';
7
-
8
- /**
9
- * Generate mock embedding for testing/fallback
10
- */
11
- export function generateMockEmbedding(text: string, dimensions = 1536): number[] {
12
- const words = text.toLowerCase().split(/\s+/);
13
- const embedding = new Array(dimensions).fill(0);
14
-
15
- // Simple hash-based pseudo-embedding
16
- for (const word of words) {
17
- let hash = 0;
18
- for (let i = 0; i < word.length; i++) {
19
- hash = (hash << 5) - hash + word.charCodeAt(i);
20
- hash &= hash; // Convert to 32-bit integer
21
- }
22
-
23
- // Distribute hash across embedding dimensions
24
- for (let i = 0; i < dimensions; i++) {
25
- embedding[i] += Math.sin(hash * (i + 1)) * 0.1;
26
- }
27
- }
28
-
29
- // Normalize the embedding
30
- const norm = Math.sqrt(embedding.reduce((sum, val) => sum + val * val, 0));
31
- if (norm > 0) {
32
- return embedding.map((val) => val / norm);
33
- }
34
-
35
- return embedding;
36
- }
37
-
38
- import fs from 'node:fs';
39
- import path from 'node:path';
40
- import * as lancedb from '@lancedb/lancedb';
41
-
42
- export interface VectorDocument {
43
- id: string;
44
- embedding: number[];
45
- metadata: {
46
- type: 'knowledge' | 'code';
47
- content: string;
48
- category: string;
49
- language: string;
50
- [key: string]: string | number | boolean;
51
- };
52
- }
53
-
54
- export interface VectorStorageMetadata {
55
- dimensions: number;
56
- count: number;
57
- }
58
-
59
- export interface VectorSearchResult {
60
- doc: VectorDocument;
61
- similarity: number;
62
- }
63
-
64
- /**
65
- * LanceDB vector storage - Local only, no cloud services
66
- */
67
- export class VectorStorage {
68
- private db: any = null;
69
- private table: any = null;
70
- private metadata: VectorStorageMetadata;
71
- private indexPath: string;
72
- private dimensions: number;
73
- private tableName = 'vectors';
74
-
75
- constructor(indexPath: string, dimensions: number) {
76
- this.indexPath = indexPath;
77
- this.dimensions = dimensions;
78
-
79
- this.metadata = {
80
- dimensions,
81
- count: 0,
82
- };
83
- }
84
-
85
- /**
86
- * Initialize the database connection
87
- */
88
- async initialize(): Promise<void> {
89
- if (this.db) {
90
- return;
91
- }
92
-
93
- try {
94
- // Ensure directory exists
95
- const dir = path.dirname(this.indexPath);
96
- if (!fs.existsSync(dir)) {
97
- fs.mkdirSync(dir, { recursive: true });
98
- }
99
-
100
- // Connect to LanceDB (local only)
101
- this.db = await lancedb.connect(this.indexPath);
102
-
103
- // Check if table exists
104
- const tables = await this.db.tableNames();
105
- if (tables.includes(this.tableName)) {
106
- this.table = await this.db.openTable(this.tableName);
107
-
108
- // Update count
109
- try {
110
- this.metadata.count = await this.table.countRows();
111
- logger.info('Loaded LanceDB table', { count: this.metadata.count });
112
- } catch (_e) {
113
- this.metadata.count = 0;
114
- }
115
- } else {
116
- // Create simple table
117
- const data = [
118
- {
119
- id: 'init',
120
- vector: new Array(this.dimensions).fill(0),
121
- type: 'code',
122
- content: '',
123
- category: '',
124
- language: '',
125
- },
126
- ];
127
-
128
- this.table = await this.db.createTable(this.tableName, data);
129
-
130
- // Remove the init record
131
- await this.table.delete('id = ?', ['init']);
132
-
133
- logger.info('Created new LanceDB table', { tableName: this.tableName });
134
- }
135
- } catch (error) {
136
- logger.error('Failed to initialize LanceDB', { error });
137
- // Fallback to simple in-memory storage
138
- this.useFallback = true;
139
- }
140
- }
141
-
142
- private useFallback = false;
143
- private fallbackData: Map<string, VectorDocument> = new Map();
144
-
145
- /**
146
- * Save index to disk
147
- */
148
- async save(): Promise<void> {
149
- if (this.useFallback) {
150
- logger.warn('Using fallback storage - save is no-op');
151
- return;
152
- }
153
-
154
- // LanceDB automatically saves
155
- logger.debug('LanceDB saves automatically');
156
- }
157
-
158
- /**
159
- * Add document to index
160
- */
161
- async addDocument(doc: VectorDocument): Promise<void> {
162
- if (doc.embedding.length !== this.dimensions) {
163
- throw new Error(
164
- `Embedding dimension mismatch: expected ${this.dimensions}, got ${doc.embedding.length}`
165
- );
166
- }
167
-
168
- if (this.useFallback) {
169
- this.fallbackData.set(doc.id, doc);
170
- this.metadata.count = this.fallbackData.size;
171
- return;
172
- }
173
-
174
- await this.initialize();
175
-
176
- try {
177
- // Add to LanceDB
178
- await this.table.add([
179
- {
180
- id: doc.id,
181
- vector: doc.embedding,
182
- type: doc.metadata.type,
183
- content: doc.metadata.content,
184
- category: doc.metadata.category,
185
- language: doc.metadata.language,
186
- },
187
- ]);
188
-
189
- this.metadata.count++;
190
- } catch (error) {
191
- logger.error('Failed to add document, falling back', { error });
192
- this.useFallback = true;
193
- this.fallbackData.set(doc.id, doc);
194
- this.metadata.count = this.fallbackData.size;
195
- }
196
- }
197
-
198
- /**
199
- * Add multiple documents
200
- */
201
- async addDocuments(docs: VectorDocument[]): Promise<void> {
202
- if (docs.length === 0) {
203
- return;
204
- }
205
-
206
- // Validate all documents
207
- for (const doc of docs) {
208
- if (doc.embedding.length !== this.dimensions) {
209
- throw new Error(
210
- `Embedding dimension mismatch: expected ${this.dimensions}, got ${doc.embedding.length}`
211
- );
212
- }
213
- }
214
-
215
- if (this.useFallback) {
216
- for (const doc of docs) {
217
- this.fallbackData.set(doc.id, doc);
218
- }
219
- this.metadata.count = this.fallbackData.size;
220
- return;
221
- }
222
-
223
- await this.initialize();
224
-
225
- try {
226
- // Convert to LanceDB format
227
- const records = docs.map((doc) => ({
228
- id: doc.id,
229
- vector: doc.embedding,
230
- type: doc.metadata.type,
231
- content: doc.metadata.content,
232
- category: doc.metadata.category,
233
- language: doc.metadata.language,
234
- }));
235
-
236
- // Batch add to LanceDB
237
- await this.table.add(records);
238
- this.metadata.count += docs.length;
239
-
240
- logger.info('Added documents to LanceDB', { count: docs.length });
241
- } catch (error) {
242
- logger.error('Failed to add documents, falling back', { error });
243
- this.useFallback = true;
244
- for (const doc of docs) {
245
- this.fallbackData.set(doc.id, doc);
246
- }
247
- this.metadata.count = this.fallbackData.size;
248
- }
249
- }
250
-
251
- /**
252
- * Search for similar documents
253
- */
254
- async search(
255
- queryEmbedding: number[],
256
- options: {
257
- k?: number;
258
- filter?: (doc: VectorDocument) => boolean;
259
- } = {}
260
- ): Promise<VectorSearchResult[]> {
261
- if (queryEmbedding.length !== this.dimensions) {
262
- throw new Error(
263
- `Query embedding dimension mismatch: expected ${this.dimensions}, got ${queryEmbedding.length}`
264
- );
265
- }
266
-
267
- const { k = 5, filter } = options;
268
-
269
- if (this.useFallback) {
270
- // Simple fallback search
271
- const results: VectorSearchResult[] = [];
272
-
273
- for (const doc of this.fallbackData.values()) {
274
- if (filter && !filter(doc)) {
275
- continue;
276
- }
277
-
278
- const similarity = this.cosineSimilarity(queryEmbedding, doc.embedding);
279
- results.push({ doc, similarity });
280
- }
281
-
282
- return results.sort((a, b) => b.similarity - a.similarity).slice(0, k);
283
- }
284
-
285
- await this.initialize();
286
-
287
- try {
288
- // Search LanceDB
289
- const query = this.table.vectorSearch(queryEmbedding).limit(k * 2);
290
- const results = await query.toArray();
291
-
292
- const filteredResults: VectorSearchResult[] = [];
293
-
294
- for (const result of results) {
295
- // Convert back to our format
296
- const doc: VectorDocument = {
297
- id: result.id,
298
- embedding: result.vector,
299
- metadata: {
300
- type: result.type as 'knowledge' | 'code',
301
- content: result.content || '',
302
- category: result.category || '',
303
- language: result.language || '',
304
- },
305
- };
306
-
307
- // Apply filter if provided
308
- if (filter && !filter(doc)) {
309
- continue;
310
- }
311
-
312
- // Convert distance to similarity
313
- const distance = result._distance || 0;
314
- const similarity = 1 / (1 + distance);
315
-
316
- filteredResults.push({
317
- doc,
318
- similarity,
319
- });
320
-
321
- // Stop if we have enough results
322
- if (filteredResults.length >= k) {
323
- break;
324
- }
325
- }
326
-
327
- return filteredResults;
328
- } catch (error) {
329
- logger.error('Vector search failed, falling back', { error });
330
- // Fallback to simple search
331
- return this.search(queryEmbedding, options);
332
- }
333
- }
334
-
335
- /**
336
- * Get document by ID
337
- */
338
- async getDocument(id: string): Promise<VectorDocument | undefined> {
339
- if (this.useFallback) {
340
- return this.fallbackData.get(id);
341
- }
342
-
343
- await this.initialize();
344
-
345
- try {
346
- // Simple scan for now (LanceDB API might be different)
347
- const results = await this.table.limit(1000).toArray();
348
- const result = results.find((r: any) => r.id === id);
349
-
350
- if (!result) {
351
- return undefined;
352
- }
353
-
354
- return {
355
- id: result.id,
356
- embedding: result.vector,
357
- metadata: {
358
- type: result.type as 'knowledge' | 'code',
359
- content: result.content || '',
360
- category: result.category || '',
361
- language: result.language || '',
362
- },
363
- };
364
- } catch (error) {
365
- logger.error('Failed to get document', { error });
366
- return this.fallbackData.get(id);
367
- }
368
- }
369
-
370
- /**
371
- * Get all documents
372
- */
373
- async getAllDocuments(): Promise<VectorDocument[]> {
374
- if (this.useFallback) {
375
- return Array.from(this.fallbackData.values());
376
- }
377
-
378
- await this.initialize();
379
-
380
- try {
381
- const results = await this.table.toArray();
382
- return results.map((result: any) => ({
383
- id: result.id,
384
- embedding: result.vector,
385
- metadata: {
386
- type: result.type as 'knowledge' | 'code',
387
- content: result.content || '',
388
- category: result.category || '',
389
- language: result.language || '',
390
- },
391
- }));
392
- } catch (error) {
393
- logger.error('Failed to get all documents', { error });
394
- return Array.from(this.fallbackData.values());
395
- }
396
- }
397
-
398
- /**
399
- * Get metadata
400
- */
401
- getMetadata(): VectorStorageMetadata {
402
- return { ...this.metadata };
403
- }
404
-
405
- /**
406
- * Clear all documents
407
- */
408
- async clear(): Promise<void> {
409
- if (this.useFallback) {
410
- this.fallbackData.clear();
411
- this.metadata.count = 0;
412
- return;
413
- }
414
-
415
- await this.initialize();
416
-
417
- try {
418
- await this.db.dropTable(this.tableName);
419
-
420
- // Recreate empty table
421
- const data = [
422
- {
423
- id: 'init',
424
- vector: new Array(this.dimensions).fill(0),
425
- type: 'code',
426
- content: '',
427
- category: '',
428
- language: '',
429
- },
430
- ];
431
-
432
- this.table = await this.db.createTable(this.tableName, data);
433
- await this.table.delete('id = ?', ['init']);
434
-
435
- this.metadata.count = 0;
436
- logger.info('Cleared all vectors from LanceDB');
437
- } catch (error) {
438
- logger.error('Failed to clear vectors', { error });
439
- this.fallbackData.clear();
440
- this.metadata.count = 0;
441
- }
442
- }
443
-
444
- /**
445
- * Load existing storage from disk
446
- */
447
- static async load(indexPath: string): Promise<VectorStorage | null> {
448
- try {
449
- if (!fs.existsSync(indexPath)) {
450
- return null;
451
- }
452
-
453
- // Try to connect to see if it's a valid LanceDB
454
- const db = await lancedb.connect(indexPath);
455
- const tables = await db.tableNames();
456
-
457
- if (tables.length === 0) {
458
- return null;
459
- }
460
-
461
- // Default to OpenAI dimensions
462
- const storage = new VectorStorage(indexPath, 1536);
463
- return storage;
464
- } catch (error) {
465
- logger.error('Failed to load LanceDB storage', { error });
466
- return null;
467
- }
468
- }
469
-
470
- /**
471
- * Calculate cosine similarity
472
- */
473
- private cosineSimilarity(a: number[], b: number[]): number {
474
- if (a.length !== b.length) {
475
- return 0;
476
- }
477
-
478
- let dotProduct = 0;
479
- let normA = 0;
480
- let normB = 0;
481
-
482
- for (let i = 0; i < a.length; i++) {
483
- dotProduct += a[i] * b[i];
484
- normA += a[i] * a[i];
485
- normB += b[i] * b[i];
486
- }
487
-
488
- if (normA === 0 || normB === 0) {
489
- return 0;
490
- }
491
-
492
- return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
493
- }
494
- }